diff --git a/config/prifi-integration-window1-oc-equiv-test.toml b/config/prifi-integration-window1-oc-equiv-test.toml index 63f03e6be..628ff4915 100644 --- a/config/prifi-integration-window1-oc-equiv-test.toml +++ b/config/prifi-integration-window1-oc-equiv-test.toml @@ -16,7 +16,7 @@ TrusteeSleepTimeBetweenMessages = 100 TrusteeAlwaysSlowDown = true TrusteeNeverSlowDown = false OverrideLogLevel = -1 -ForceConsoleColor = true +ForceConsoleColor = true RelayReportingLimit = -1 SocksServerPort = 8080 SocksClientPort = 8090 diff --git a/config/prifi.toml b/config/prifi.toml index d77886fdd..f79294ecb 100644 --- a/config/prifi.toml +++ b/config/prifi.toml @@ -1,15 +1,15 @@ -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 @@ -17,18 +17,19 @@ 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 \ No newline at end of file diff --git a/prifi-lib/client/client.go b/prifi-lib/client/client.go index 04d94ab3f..f16084524 100644 --- a/prifi-lib/client/client.go +++ b/prifi-lib/client/client.go @@ -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" ) @@ -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") @@ -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 { @@ -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 @@ -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{ @@ -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 @@ -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, @@ -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) @@ -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) @@ -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{ diff --git a/prifi-lib/client/client_test.go b/prifi-lib/client/client_test.go index 03c590635..cdda32078 100644 --- a/prifi-lib/client/client_test.go +++ b/prifi-lib/client/client_test.go @@ -9,7 +9,8 @@ import ( "github.com/dedis/prifi/prifi-lib/dcnet" prifilog "github.com/dedis/prifi/prifi-lib/log" "github.com/dedis/prifi/prifi-lib/net" - "github.com/dedis/prifi/prifi-lib/relay" + //"github.com/dedis/prifi/prifi-lib/relay" + "crypto/sha256" "github.com/dedis/prifi/prifi-lib/scheduler" "go.dedis.ch/kyber" "go.dedis.ch/onet/log" @@ -701,28 +702,27 @@ func TestDisruptionClient(t *testing.T) { dcNetDecoded[i] = pad1.Payload[i] ^ pad2.Payload[i] ^ clientPad.Payload[i] i++ } - log.Error("dcNetDecoded", dcNetDecoded) - - hmac := dcNetDecoded[0:32] - data := dcNetDecoded[32:] - - success := relay.ValidateHmac256(data, hmac, clientID) - if !success { - t.Error("HMAC should be valid") + b_echo_last := dcNetDecoded[0] + if b_echo_last != 0 { + t.Error("The first b_echo_last flag should always be 0, now its:", b_echo_last) } // now in a normal round (possibly the client will send 0's but it's a different path) - //Receive some data down - dataDown := []byte{1, 2, 3} + // Receive some data down which is the CORRECT HASH of the previous message + [1, 2, 3] + hash := sha256.Sum256(dcNetDecoded[1:]) + data := []byte{1, 2, 3} + msg7 := net.REL_CLI_DOWNSTREAM_DATA{ - RoundID: 1, - Data: dataDown, - FlagResync: false, + RoundID: 1, + Data: data, + FlagResync: false, + HashOfPreviousUpstreamData: hash[:], } err := client.ReceivedMessage(msg7) if err != nil { t.Error("Client should be able to receive this data") } + msg8 := sentToRelay[0].(*net.CLI_REL_UPSTREAM_DATA) sentToRelay = make([]interface{}, 0) @@ -738,20 +738,20 @@ func TestDisruptionClient(t *testing.T) { i++ } - hmac = dcNetDecoded[0:32] - data = dcNetDecoded[32:] - - success = relay.ValidateHmac256(data, hmac, clientID) - if !success { - t.Error("HMAC should be valid") + b_echo_last = dcNetDecoded[0] + if b_echo_last != 0 { + t.Error("The b_echo_last flag be 0, now its:", b_echo_last) } // now with disruption - //Receive some data down + //Receive some data down. Now the same data, but without the hash + data = []byte{1, 2, 3} + msg9 := net.REL_CLI_DOWNSTREAM_DATA{ - RoundID: 2, - Data: dataDown, - FlagResync: false, + RoundID: 2, + Data: data, + FlagResync: false, + HashOfPreviousUpstreamData: make([]byte, 0), } err = client.ReceivedMessage(msg9) if err != nil { @@ -760,37 +760,20 @@ func TestDisruptionClient(t *testing.T) { msg10 := sentToRelay[0].(*net.CLI_REL_UPSTREAM_DATA) sentToRelay = make([]interface{}, 0) - //disruption ! - if msg10.Data[upCellSize-1] == 0 { - msg10.Data[upCellSize-1] = 255 - } else { - msg10.Data[upCellSize-1] = 0 - } - //dcnet decode - pad1 = dcnet.DCNetCipherFromBytes(t1.TrusteeEncodeForRound(3)) - pad2 = dcnet.DCNetCipherFromBytes(t2.TrusteeEncodeForRound(3)) + pad1 = dcnet.DCNetCipherFromBytes(t1.TrusteeEncodeForRound(2)) + pad2 = dcnet.DCNetCipherFromBytes(t2.TrusteeEncodeForRound(2)) clientPad = dcnet.DCNetCipherFromBytes(msg10.Data) + dcNetDecoded = make([]byte, upCellSize) i = 0 for i < len(dcNetDecoded) { dcNetDecoded[i] = pad1.Payload[i] ^ pad2.Payload[i] ^ clientPad.Payload[i] i++ } - hmac = dcNetDecoded[0:32] - data = dcNetDecoded[32:] - - success = relay.ValidateHmac256(data, hmac, clientID) - if success { - t.Error("HMAC should not be valid") - } - //re-bitflip to original - data[len(data)-1] = 0 - - //should fail, wrong client ID - success = relay.ValidateHmac256(data, hmac, clientID+1) - if success { - t.Error("HMAC should not be valid") + b_echo_last = dcNetDecoded[0] + if b_echo_last != 1 { + t.Error("The b_echo_last flag should be 1, now its:", b_echo_last) } t.SkipNow() //we started a goroutine, let's kill everything, we're good diff --git a/prifi-lib/client/disruption.go b/prifi-lib/client/disruption.go new file mode 100644 index 000000000..c65dd813e --- /dev/null +++ b/prifi-lib/client/disruption.go @@ -0,0 +1,205 @@ +package client + +import ( + "bytes" + "fmt" + "github.com/dedis/prifi/prifi-lib/config" + "github.com/dedis/prifi/prifi-lib/net" + "go.dedis.ch/kyber" + "go.dedis.ch/kyber/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...) + log.Lvl1("CARLOS EXPLODE: ", pred) + + 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) + // CARLOS 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 { + log.Lvl1("POSSIBLE DISRUPTION!", p.clientState.MyLastRound, p.clientState.RoundNo-1) + 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 +} diff --git a/prifi-lib/client/init.go b/prifi-lib/client/init.go index 0d2478188..9c3d0e5e4 100644 --- a/prifi-lib/client/init.go +++ b/prifi-lib/client/init.go @@ -43,6 +43,11 @@ type ClientState struct { NextDataForDCNet *[]byte //if not nil, send this before polling DataForDCNet DataFromDCNet chan []byte //Data from the relay : VPN / SOCKS should read data from there ! DataOutputEnabled bool //if FALSE, nothing will be written to DataFromDCNet + HashFromPreviousMessage [32]byte + MyLastRound int32 + LastMessage []byte + B_echo_last byte + DisruptionWrongBitPosition int ephemeralPrivateKey kyber.Scalar EphemeralPublicKey kyber.Point ID int @@ -65,6 +70,10 @@ type ClientState struct { DisruptionProtectionEnabled bool LastWantToSend time.Time EquivocationProtectionEnabled bool + EphemeralPublicKeys []kyber.Point + // TEST DISRUPTION + ForceDisruptionSinceRound3 bool + AllreadyDisrupted bool //concurrent stuff RoundNo int32 @@ -166,6 +175,14 @@ func (p *PriFiLibClientInstance) ReceivedMessage(msg interface{}) error { if p.stateMachine.AssertState("EPH_KEYS_SENT") { err = p.Received_REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG(typedMsg) } + case net.REL_ALL_DISRUPTION_REVEAL: + if p.stateMachine.AssertState("READY") { + err = p.Received_REL_ALL_DISRUPTION_REVEAL(typedMsg) + } + case net.REL_ALL_REVEAL_SHARED_SECRETS: + if p.stateMachine.AssertState("READY") { + err = p.Received_REL_ALL_REVEAL_SHARED_SECRETS(typedMsg) + } default: err = errors.New("Unrecognized message, type" + reflect.TypeOf(msg).String()) } diff --git a/prifi-lib/dcnet/dcnet.go b/prifi-lib/dcnet/dcnet.go index a724e3852..aee6f9386 100644 --- a/prifi-lib/dcnet/dcnet.go +++ b/prifi-lib/dcnet/dcnet.go @@ -141,18 +141,45 @@ func (e *DCNetEntity) verbosePrint(info ...interface{}) { // Encodes "Payload" in the correct round. Will skip PRNG material if the round is in the future, // and crash if the round is in the past or the Payload is too long func (e *DCNetEntity) TrusteeEncodeForRound(roundID int32) []byte { - return e.EncodeForRound(roundID, false, nil) + upstreamCell, _ := e.EncodeForRound(roundID, false, nil) + return upstreamCell } // Encodes "Payload" in the correct round. Will skip PRNG material if the round is in the future, // and crash if the round is in the past or the Payload is too long -func (e *DCNetEntity) EncodeForRound(roundID int32, slotOwner bool, payload []byte) []byte { +func (e *DCNetEntity) EncodeForRound(roundID int32, slotOwner bool, payload []byte) ([]byte, []byte) { if len(payload) > e.DCNetPayloadSize { panic("DCNet: cannot encode Payload of length " + strconv.Itoa(int(len(payload))) + " max length is " + strconv.Itoa(len(payload))) } if roundID < e.currentRound { - panic("DCNet: asked to encode for round " + strconv.Itoa(int(roundID)) + " but we are at round " + strconv.Itoa(int(e.currentRound))) + sharedKeys := e.sharedKeys + + // Use the provided shared secrets to seed a pseudorandom DC-nets ciphers shared with each peer. + sharedPRNGsCopy := make([]kyber.XOF, len(sharedKeys)) + for i := range sharedKeys { + e.verbosePrint("key", i, ":", sharedKeys[i]) + seed, err := sharedKeys[i].MarshalBinary() + if err != nil { + log.Fatal("Could not extract data from shared key", err) + } + sharedPRNGsCopy[i] = e.cryptoSuite.XOF(seed) + } + round := int32(0) + for round < roundID { + //discard crypto material + + // consume the PRNGs + for i := range e.sharedPRNGs { + dummy := make([]byte, e.DCNetPayloadSize) + sharedPRNGsCopy[i].XORKeyStream(dummy, dummy) + } + + round++ + + } + e.sharedPRNGs = sharedPRNGsCopy + e.currentRound = roundID } for e.currentRound < roundID { @@ -167,10 +194,10 @@ func (e *DCNetEntity) EncodeForRound(roundID int32, slotOwner bool, payload []by e.currentRound++ } - + var plainPayload []byte var c *DCNetCipher if e.Entity == DCNET_CLIENT { - c = e.clientEncode(slotOwner, payload) + c, plainPayload = e.clientEncode(slotOwner, payload) } else { c = e.trusteeEncode() } @@ -178,8 +205,7 @@ func (e *DCNetEntity) EncodeForRound(roundID int32, slotOwner bool, payload []by e.verbosePrint("r[", roundID, "]:\n", c.Payload) e.verbosePrint("r[", roundID, "]: equiv\n", c.EquivocationProtectionTag) - - return c.ToBytes() + return c.ToBytes(), plainPayload } // Adds `newdata` into the sponge representing the received downstream data @@ -189,14 +215,20 @@ func (e *DCNetEntity) UpdateReceivedMessageHistory(newData []byte) { } } -func (e *DCNetEntity) clientEncode(slotOwner bool, payload []byte) *DCNetCipher { +// Encode for clients +func (e *DCNetEntity) clientEncode(slotOwner bool, payload []byte) (*DCNetCipher, []byte) { + c := new(DCNetCipher) if payload == nil { payload = make([]byte, e.DCNetPayloadSize) } else { // deep clone and pad - payload2 := make([]byte, e.DCNetPayloadSize) + dcnetPayloadSize := e.DCNetPayloadSize + if e.EquivocationProtectionEnabled && slotOwner { + dcnetPayloadSize -= 16 + } + payload2 := make([]byte, dcnetPayloadSize) copy(payload2[0:len(payload)], payload) payload = payload2 } @@ -208,10 +240,12 @@ func (e *DCNetEntity) clientEncode(slotOwner bool, payload []byte) *DCNetCipher p_ij[i] = make([]byte, e.DCNetPayloadSize) e.sharedPRNGs[i].XORKeyStream(p_ij[i], p_ij[i]) } + plainPayload := make([]byte, e.DCNetPayloadSize) // if the equivocation protection is enabled, encrypt the Payload, and add the tag if e.EquivocationProtectionEnabled { payload, sigma_j := e.equivocationProtection.ClientEncryptPayload(slotOwner, payload, p_ij) + copy(plainPayload[:], payload) e.verbosePrint("payload\n", payload) e.verbosePrint("sigma_j\n", sigma_j) c.Payload = payload // replace the Payload with the encrypted version @@ -224,10 +258,11 @@ func (e *DCNetEntity) clientEncode(slotOwner bool, payload []byte) *DCNetCipher c.Payload[k] ^= p_ij[i][k] // XORs in the pads } } - - return c + log.Lvl1("CARLOS: post XOR", c.Payload) + return c, plainPayload[:] } +// Encode for trustees func (e *DCNetEntity) trusteeEncode() *DCNetCipher { c := new(DCNetCipher) @@ -256,6 +291,72 @@ func (e *DCNetEntity) trusteeEncode() *DCNetCipher { return c } +// Function to get the bits from previous round in an exact position. +func (e *DCNetEntity) GetBitsOfRound(roundID int32, bitPosition int32) (map[int]int, [][]byte) { + log.Lvl1("CARLOS ROUND:", roundID) + if roundID >= e.currentRound { + return nil, nil + } + + sharedKeys := e.sharedKeys + + // Use the provided shared secrets to seed a pseudorandom DC-nets ciphers shared with each peer. + sharedPRNGsCopy := make([]kyber.XOF, len(sharedKeys)) + for i := range sharedKeys { + e.verbosePrint("key", i, ":", sharedKeys[i]) + seed, err := sharedKeys[i].MarshalBinary() + if err != nil { + log.Fatal("Could not extract data from shared key", err) + } + sharedPRNGsCopy[i] = e.cryptoSuite.XOF(seed) + } + round := int32(0) + for round < roundID { + //discard crypto material + + // consume the PRNGs + for i := range e.sharedPRNGs { + dummy := make([]byte, e.DCNetPayloadSize) + sharedPRNGsCopy[i].XORKeyStream(dummy, dummy) + } + + round++ + + } + e.sharedPRNGs = sharedPRNGsCopy + e.currentRound = roundID + + rtn := make(map[int]int) + + // prepare the pads + + p_ij := make([][]byte, len(e.sharedPRNGs)) + for i := range p_ij { + p_ij[i] = make([]byte, e.DCNetPayloadSize) + e.sharedPRNGs[i].XORKeyStream(p_ij[i], p_ij[i]) + } + // DC-net encrypt the Payload + for i := range p_ij { + bytePosition := int(bitPosition / 8) + // TODO: CHECK WHY THIS HAPPEN, CLEARLY A BUG HERE + if !e.EquivocationProtectionEnabled { + bytePosition++ + } + byte_toGet := p_ij[i][bytePosition] + log.Lvl1("CARLOS BYTE:", byte_toGet) + bitInByte := (8-bitPosition%8)%8 - 1 + mask := byte(1 << uint(bitInByte)) + if (byte_toGet & mask) == 0 { + rtn[i] = 0 + } else { + rtn[i] = 1 + } + + } + + return rtn, p_ij +} + // Used by the relay to start decoding a round func (e *DCNetEntity) DecodeStart(roundID int32) { e.DCNetRoundDecoder = new(DCNetRoundDecoder) @@ -304,14 +405,17 @@ func (e *DCNetEntity) DecodeTrustee(roundID int32, slice []byte) { } // Called on the relay to decode the cell, after having stored the cryptographic materials -func (e *DCNetEntity) DecodeCell() []byte { +func (e *DCNetEntity) DecodeCell(isOpenClosedSlot bool) ([]byte, []byte) { //No Equivocation -> just XOR d := e.DCNetRoundDecoder - decoded := d.xorBuffer - if e.EquivocationProtectionEnabled { + cipherText := d.xorBuffer + var decoded []byte + if e.EquivocationProtectionEnabled && !isOpenClosedSlot { decoded = e.equivocationProtection.RelayDecode(d.xorBuffer, d.equivTrusteeContribs, d.equivClientContribs) + } else { + decoded = cipherText } - return decoded + return decoded, cipherText } diff --git a/prifi-lib/dcnet/dcnet_test.go b/prifi-lib/dcnet/dcnet_test.go index f278ce7f2..3f3cf13b8 100644 --- a/prifi-lib/dcnet/dcnet_test.go +++ b/prifi-lib/dcnet/dcnet_test.go @@ -124,7 +124,11 @@ func SimulateRounds(t *testing.T, tg *TestGroup, maxRounds int32) { clientMessages := make([][]byte, 0) trusteesMessages := make([][]byte, 0) first := true - message := randomBytes(d.DCNetPayloadSize) + dcNetPayloadSize := d.DCNetPayloadSize + if d.EquivocationProtectionEnabled { + dcNetPayloadSize -= 16 + } + message := randomBytes(dcNetPayloadSize) downstreamMessage := randomBytes(d.DCNetPayloadSize) //used only to update the history for i := range tg.Clients { @@ -137,10 +141,10 @@ func SimulateRounds(t *testing.T, tg *TestGroup, maxRounds int32) { var m []byte if first { //fmt.Println("Embedding message:", message) - m = tg.Clients[i].DCNetEntity.EncodeForRound(roundID, true, message) + m, _ = tg.Clients[i].DCNetEntity.EncodeForRound(roundID, true, message) first = false } else { - m = tg.Clients[i].DCNetEntity.EncodeForRound(roundID, false, nil) + m, _ = tg.Clients[i].DCNetEntity.EncodeForRound(roundID, false, nil) } clientMessages = append(clientMessages, m) } @@ -160,7 +164,7 @@ func SimulateRounds(t *testing.T, tg *TestGroup, maxRounds int32) { tg.Relay.DCNetEntity.DecodeTrustee(roundID, m) } - output := tg.Relay.DCNetEntity.DecodeCell() + output, _ := tg.Relay.DCNetEntity.DecodeCell(false) //fmt.Println("-----------------") //fmt.Println(output) diff --git a/prifi-lib/dcnet/equivocation.go b/prifi-lib/dcnet/equivocation.go index 2594d9d52..1d38871d2 100644 --- a/prifi-lib/dcnet/equivocation.go +++ b/prifi-lib/dcnet/equivocation.go @@ -1,6 +1,8 @@ package dcnet import ( + "crypto/aes" + "crypto/cipher" "crypto/rand" "crypto/sha256" "github.com/dedis/prifi/prifi-lib/config" @@ -35,7 +37,7 @@ func NewEquivocation() *EquivocationProtection { e.suite = config.CryptoSuite e.history = e.suite.Scalar().One() - randomKey := make([]byte, 100) + randomKey := make([]byte, 32) rand.Read(randomKey) e.randomness = e.suite.XOF(randomKey) @@ -85,6 +87,7 @@ func (e *EquivocationProtection) ClientEncryptPayload(slotOwner bool, x []byte, if err != nil { log.Fatal("Couldn't marshall", err) } + return x, kappa_i_bytes } @@ -95,10 +98,22 @@ func (e *EquivocationProtection) ClientEncryptPayload(slotOwner bool, x []byte, } // encrypt payload - for i := range x { - x[i] ^= k_i_bytes[i%len(k_i_bytes)] + // LB->CV: Replace by traditional encryption (AES-GCM or what not) instead of XOR + + block, err := aes.NewCipher(k_i_bytes) + if err != nil { + panic(err.Error()) } + nonce := make([]byte, 12) + + aesgcm, err := cipher.NewGCM(block) + if err != nil { + panic(err.Error()) + } + + x = aesgcm.Seal(nil, nonce, x, nil) + log.Lvl1("THIS IS IT:", x) // compute kappa kappa_i := k_i.Add(k_i, product) kappa_i_bytes, err := kappa_i.MarshalBinary() @@ -108,6 +123,12 @@ func (e *EquivocationProtection) ClientEncryptPayload(slotOwner bool, x []byte, return x, kappa_i_bytes } +// LB->CV todo +func (e *EquivocationProtection) ClientProve() []byte { + + return nil +} + // a function that takes returns the byte[] version of sigma_j func (e *EquivocationProtection) TrusteeGetContribution(s_i [][]byte) []byte { @@ -132,6 +153,12 @@ func (e *EquivocationProtection) TrusteeGetContribution(s_i [][]byte) []byte { return kappa_j_bytes } +// LB->CV todo +func (e *EquivocationProtection) TrusteeProve() []byte { + + return nil +} + // given all contributions, decodes the payload func (e *EquivocationProtection) RelayDecode(encryptedPayload []byte, trusteesContributions [][]byte, clientsContributions [][]byte) []byte { @@ -185,9 +212,26 @@ func (e *EquivocationProtection) RelayDecode(encryptedPayload []byte, trusteesCo } // decrypt the payload - for i := range encryptedPayload { - encryptedPayload[i] ^= k_bytes[i%len(k_bytes)] + nonce := make([]byte, 12) + + block, err := aes.NewCipher(k_bytes) + if err != nil { + panic(err.Error()) + } + + aesgcm, err := cipher.NewGCM(block) + if err != nil { + panic(err.Error()) + } + + message, err := aesgcm.Open(nil, nonce, encryptedPayload, nil) + if err != nil { + //CARLOS TODO: DISRUPTION + log.Lvl1("DISRUPTION, CANNOT DECODE") + message = make([]byte, len(encryptedPayload)-16) + } else { + log.Lvl1("CORRECT DECRYPTION:", encryptedPayload, message) } - return encryptedPayload + return message } diff --git a/prifi-lib/dcnet/equivocation_test.go b/prifi-lib/dcnet/equivocation_test.go index b9def992c..a11e2c270 100644 --- a/prifi-lib/dcnet/equivocation_test.go +++ b/prifi-lib/dcnet/equivocation_test.go @@ -47,8 +47,10 @@ func equivocationTestForDataLength(t *testing.T, payloadSize int) { // get the pads padRound2_t := DCNetCipherFromBytes(dcnet_Trustee.TrusteeEncodeForRound(0)) - padRound1_c1 := DCNetCipherFromBytes(dcnet_Client1.EncodeForRound(0, true, data)) - padRound1_c2 := DCNetCipherFromBytes(dcnet_Client2.EncodeForRound(0, false, nil)) + encode_for_round_1, _ := dcnet_Client1.EncodeForRound(0, true, data) + padRound1_c1 := DCNetCipherFromBytes(encode_for_round_1) + encode_for_round_2, _ := dcnet_Client2.EncodeForRound(0, false, nil) + padRound1_c2 := DCNetCipherFromBytes(encode_for_round_2) res := make([]byte, payloadSize) for i := range padRound1_c2.Payload { diff --git a/prifi-lib/dcnet/profile.tmp b/prifi-lib/dcnet/profile.tmp new file mode 100644 index 000000000..79b28a0b6 --- /dev/null +++ b/prifi-lib/dcnet/profile.tmp @@ -0,0 +1 @@ +mode: atomic diff --git a/prifi-lib/net/messages.go b/prifi-lib/net/messages.go index 77f25ccb9..22211af21 100644 --- a/prifi-lib/net/messages.go +++ b/prifi-lib/net/messages.go @@ -64,11 +64,12 @@ type CLI_REL_OPENCLOSED_DATA struct { // REL_CLI_DOWNSTREAM_DATA message contains the downstream data for a client for a given round // and is sent by the relay to the clients. type REL_CLI_DOWNSTREAM_DATA struct { - RoundID int32 - OwnershipID int // ownership may vary with open or closed slots - Data []byte - FlagResync bool - FlagOpenClosedRequest bool + RoundID int32 + OwnershipID int // ownership may vary with open or closed slots + HashOfPreviousUpstreamData []byte + Data []byte + FlagResync bool + FlagOpenClosedRequest bool } //Converts []ByteArray -> [][]byte and returns it @@ -191,7 +192,9 @@ func (m *REL_CLI_DOWNSTREAM_DATA_UDP) SetContent(data REL_CLI_DOWNSTREAM_DATA) { func (m *REL_CLI_DOWNSTREAM_DATA_UDP) ToBytes() ([]byte, error) { //convert the message to bytes - buf := make([]byte, 4+4+len(m.REL_CLI_DOWNSTREAM_DATA.Data)+4+4) + hashLen := len(m.REL_CLI_DOWNSTREAM_DATA.HashOfPreviousUpstreamData) + buf := make([]byte, 4+4+4+hashLen+len(m.REL_CLI_DOWNSTREAM_DATA.Data)+4+4) + resyncInt := 0 if m.REL_CLI_DOWNSTREAM_DATA.FlagResync { resyncInt = 1 @@ -201,12 +204,19 @@ func (m *REL_CLI_DOWNSTREAM_DATA_UDP) ToBytes() ([]byte, error) { openclosedInt = 1 } - // [0:4 roundID] [4:8 roundID] [8:end-8 data] [end-8:end-4 resyncFlag] [end-4:end openClosedFlag] + // [0:4 roundID] [4:8 OwnershipID] [8:12 Length of Hash] [Variable: Hash] [8:end-8 data] [end-8:end-4 resyncFlag] [end-4:end openClosedFlag] binary.BigEndian.PutUint32(buf[0:4], uint32(m.REL_CLI_DOWNSTREAM_DATA.RoundID)) binary.BigEndian.PutUint32(buf[4:8], uint32(m.REL_CLI_DOWNSTREAM_DATA.OwnershipID)) + binary.BigEndian.PutUint32(buf[8:12], uint32(hashLen)) + startIndex := 12 + if hashLen > 0 { + copy(buf[12:12+hashLen], m.REL_CLI_DOWNSTREAM_DATA.HashOfPreviousUpstreamData) + startIndex += hashLen + } + binary.BigEndian.PutUint32(buf[len(buf)-8:len(buf)-4], uint32(resyncInt)) //todo : to be coded on one byte binary.BigEndian.PutUint32(buf[len(buf)-4:], uint32(openclosedInt)) //todo : to be coded on one byte - copy(buf[8:len(buf)-8], m.REL_CLI_DOWNSTREAM_DATA.Data) + copy(buf[startIndex:len(buf)-8], m.REL_CLI_DOWNSTREAM_DATA.Data) return buf, nil @@ -221,12 +231,14 @@ func (m *REL_CLI_DOWNSTREAM_DATA_UDP) FromBytes(buffer []byte) (interface{}, err return REL_CLI_DOWNSTREAM_DATA_UDP{}, errors.New(e) } - // [0:4 roundID] [4:end-8 data] [end-8:end-4 resyncFlag] [end-4:end openClosedFlag] + // [0:4 roundID] [4:8 OwnershipID] [8:12 Length of Hash] [Variable: Hash] [8:end-8 data] [end-8:end-4 resyncFlag] [end-4:end openClosedFlag] roundID := int32(binary.BigEndian.Uint32(buffer[0:4])) ownerShipID := int(binary.BigEndian.Uint32(buffer[4:8])) + hashLen := int(binary.BigEndian.Uint32(buffer[8:12])) flagResyncInt := int(binary.BigEndian.Uint32(buffer[len(buffer)-8 : len(buffer)-4])) flagOpenClosedInt := int(binary.BigEndian.Uint32(buffer[len(buffer)-4:])) - data := buffer[8 : len(buffer)-8] + hashOfPreviousUpstreamData := buffer[12 : 12+hashLen] + data := buffer[12+hashLen : len(buffer)-8] flagResync := false if flagResyncInt == 1 { @@ -237,7 +249,7 @@ func (m *REL_CLI_DOWNSTREAM_DATA_UDP) FromBytes(buffer []byte) (interface{}, err flagOpenClosed = true } - innerMessage := REL_CLI_DOWNSTREAM_DATA{roundID, ownerShipID, data, flagResync, flagOpenClosed} + innerMessage := REL_CLI_DOWNSTREAM_DATA{roundID, ownerShipID, hashOfPreviousUpstreamData, data, flagResync, flagOpenClosed} resultMessage := REL_CLI_DOWNSTREAM_DATA_UDP{innerMessage} return resultMessage, nil @@ -254,39 +266,52 @@ type CLI_REL_DISRUPTION_BLAME struct { RoundID int32 NIZK []byte BitPos int + Pval map[string]kyber.Point } // REL_ALL_DISRUPTION_REVEAL contains a disrupted roundID and the position where a bit was flipped, and is sent by the relay type REL_ALL_DISRUPTION_REVEAL struct { RoundID int32 BitPos int + NIZK []byte + Pval map[string]kyber.Point } // CLI_REL_DISRUPTION_REVEAL contains a map with individual bits to find a disruptor, and is sent to the relay type CLI_REL_DISRUPTION_REVEAL struct { ClientID int Bits map[int]int + NIZK []byte + Pval map[string]kyber.Point } // TRU_REL_DISRUPTION_REVEAL contains a map with individual bits to find a disruptor, and is sent to the relay type TRU_REL_DISRUPTION_REVEAL struct { TrusteeID int Bits map[int]int + NIZK []byte + Pval map[string]kyber.Point } -// REL_ALL_DISRUPTION_SECRET contains request ro reveal the shared secret with the specified recipient, and is sent by the relay -type REL_ALL_DISRUPTION_SECRET struct { - UserID int +// REL_ALL_REVEAL_SHARED_SECRETS contains request ro reveal the shared secret with the specified recipient, and is sent by the relay +type REL_ALL_REVEAL_SHARED_SECRETS struct { + EntityID int } -// CLI_REL_DISRUPTION_SECRET contains the shared secret requested by the relay, with a proof we computed it correctly -type CLI_REL_DISRUPTION_SECRET struct { - Secret kyber.Point - NIZK []byte +// CLI_REL_SHARED_SECRET contains the shared secret requested by the relay, with a proof we computed it correctly +type CLI_REL_SHARED_SECRET struct { + ClientID int + TrusteeID int + Secret kyber.Point + NIZK []byte + Pub map[string]kyber.Point } -// TRU_REL_DISRUPTION_SECRET contains the shared secret requested by the relay, with a proof we computed it correctly -type TRU_REL_DISRUPTION_SECRET struct { - Secret kyber.Point - NIZK []byte +// TRU_REL_SHARED_SECRET contains the shared secret requested by the relay, with a proof we computed it correctly +type TRU_REL_SHARED_SECRET struct { + TrusteeID int + ClientID int + Secret kyber.Point + NIZK []byte + Pub map[string]kyber.Point } diff --git a/prifi-lib/relay/bufferableRoundManager.go b/prifi-lib/relay/bufferableRoundManager.go index 7071ff17d..f623a1095 100644 --- a/prifi-lib/relay/bufferableRoundManager.go +++ b/prifi-lib/relay/bufferableRoundManager.go @@ -674,6 +674,5 @@ func (b *BufferableRoundManager) addToBuffer(bufferPtr *map[int]map[int32][]byte if buffer[entityID] == nil { buffer[entityID] = make(map[int32][]byte) } - buffer[entityID][roundID] = data } diff --git a/prifi-lib/relay/disruption.go b/prifi-lib/relay/disruption.go index 9aa08e901..ec4a94846 100644 --- a/prifi-lib/relay/disruption.go +++ b/prifi-lib/relay/disruption.go @@ -1,24 +1,51 @@ package relay import ( + "github.com/dedis/prifi/prifi-lib/config" "github.com/dedis/prifi/prifi-lib/net" "go.dedis.ch/kyber" "go.dedis.ch/onet/log" + + "fmt" + "go.dedis.ch/kyber/proof" "strconv" ) // Received_CLI_REL_BLAME -func (p *PriFiLibRelayInstance) Received_CLI_REL_BLAME(msg net.CLI_REL_DISRUPTION_BLAME) error { - +// CARLOS NEEDS TO IMPLMENT THIS +func (p *PriFiLibRelayInstance) Received_CLI_REL_DISRUPTION_BLAME(msg net.CLI_REL_DISRUPTION_BLAME) error { // TODO: Check NIZK - p.stateMachine.ChangeState("BLAMING") + pred := proof.Rep("X", "x", "B") + suite := config.CryptoSuite + //B := suite.Point().Base() + /*for _, key := range(p.relayState.EphemeralPublicKeys) { + pval := map[string]kyber.Point{"B": B, "X": key} + verifier := pred.Verifier(suite, pval) + err := proof.HashVerify(suite, "DISRUPTION", verifier, msg.NIZK) + if err != nil { + log.Lvl1("Proof failed to verify: ", key) + continue + } + log.Lvl1("Proof verified.", key) + }*/ + verifier := pred.Verifier(suite, msg.Pval) + err := proof.HashVerify(suite, "DISRUPTION", verifier, msg.NIZK) + if err != nil { + log.Fatal("Proof failed to verify: ") + } + log.Lvl1("Proof verified.") + + // CARLOS TODO: p.stateMachine.ChangeState("BLAMING") toSend := &net.REL_ALL_DISRUPTION_REVEAL{ RoundID: msg.RoundID, - BitPos: msg.BitPos} - - p.relayState.blamingData[0] = int(msg.RoundID) - p.relayState.blamingData[1] = msg.BitPos + BitPos: msg.BitPos, + Pval: msg.Pval, + NIZK: msg.NIZK, + } + log.Lvl1("CARLOS: POS", msg.BitPos) + p.relayState.blamingData.RoundID = msg.RoundID + p.relayState.blamingData.BitPos = msg.BitPos // broadcast to all trustees for j := 0; j < p.relayState.nTrustees; j++ { @@ -38,82 +65,226 @@ func (p *PriFiLibRelayInstance) Received_CLI_REL_BLAME(msg net.CLI_REL_DISRUPTIO } /* -Received_CLI_REL_REVEAL handles CLI_REL_REVEAL messages -Put bits in maps and find the disruptor if we received everything -*/ -func (p *PriFiLibRelayInstance) Received_CLI_REL_REVEAL(msg net.CLI_REL_DISRUPTION_REVEAL) error { +* Received_CLI_REL_DISRUPTION_REVEAL handles CLI_REL_DISRUPTION_REVEAL messages +* First, saves the bits reveal by the client. +* It checks that the bits received by the client matches with the ones of the disruptive round. +* For this it XORs the bits revealed together and compares it to the bit in the disruptive position. +* If there is a mismatch, the client is the disruptor. +* Else checks if all the reveals are received to move to next blame phase. + */ +func (p *PriFiLibRelayInstance) Received_CLI_REL_DISRUPTION_REVEAL(msg net.CLI_REL_DISRUPTION_REVEAL) error { + + log.Lvl1("Disruption Phase 1: Received bits from Client", msg.ClientID, "value", msg.Bits) + var pred_array []proof.Predicate + suite := config.CryptoSuite + for i := 1; i < p.relayState.nTrustees; i++ { + i_string := strconv.Itoa(i) + pred_array = append(pred_array, proof.Rep("T"+i_string, "t"+i_string, "B")) + } + pred := proof.And(pred_array...) + verifier := pred.Verifier(suite, msg.Pval) + err := proof.HashVerify(suite, "DISRUPTION", verifier, msg.NIZK) + if err != nil { + log.Fatal("Proof failed to verify: ") + } + log.Lvl3("Proof verified.") p.relayState.clientBitMap[msg.ClientID] = msg.Bits - if (len(p.relayState.clientBitMap) == p.relayState.nClients) && (len(p.relayState.trusteeBitMap) == p.relayState.nTrustees) { - p.findDisruptor() + result := p.compareBits(msg.ClientID, msg.Bits, p.relayState.CiphertextsHistoryClients) + if !result { + log.Fatal("Disruption Phase 1: Disruptor is Client", msg.ClientID, ".") + } else if (len(p.relayState.clientBitMap) == p.relayState.nClients) && (len(p.relayState.trusteeBitMap) == p.relayState.nTrustees) { + log.Lvl1("Disruption Phase 1: Trustee", msg.ClientID, ", is consistent with itself, checking mismatches with all trustees...") + mismatch := p.checkMismatchingPairs() + if mismatch { + toClient := &net.REL_ALL_REVEAL_SHARED_SECRETS{ + EntityID: p.relayState.blamingData.TrusteeID, + } + toTrustee := &net.REL_ALL_REVEAL_SHARED_SECRETS{ + EntityID: p.relayState.blamingData.ClientID, + } + p.messageSender.SendToTrusteeWithLog(p.relayState.blamingData.ClientID, toTrustee, "") + p.messageSender.SendToClientWithLog(p.relayState.blamingData.TrusteeID, toClient, "") + } else { + log.Fatal("Disruption Phase 2: No mismatching pairs ? this should never occur.") + } } + return nil } /* -Received_TRU_REL_REVEAL handles TRU_REL_REVEAL messages -Put bits in maps and find the disruptor if we received everything -*/ -func (p *PriFiLibRelayInstance) Received_TRU_REL_REVEAL(msg net.TRU_REL_DISRUPTION_REVEAL) error { +* Received_TRU_REL_DISRUPTION_REVEAL handles TRU_REL_DISRUPTION_REVEAL messages +* First, saves the bits reveal by the trustee. +* It checks that the bits received by the trustee matches with the ones of the disruptive round. +* For this it XORs the bits revealed together and compares it to the bit in the disruptive position. +* If there is a mismatch, the trustee is the disruptor. +* Else checks if all the reveals are received to move to next blame phase. + */ +func (p *PriFiLibRelayInstance) Received_TRU_REL_DISRUPTION_REVEAL(msg net.TRU_REL_DISRUPTION_REVEAL) error { - p.relayState.trusteeBitMap[msg.TrusteeID] = msg.Bits + log.Lvl1("Disruption Phase 1: Received bits from Trustee", msg.TrusteeID, "value", msg.Bits) - if (len(p.relayState.clientBitMap) == p.relayState.nClients) && (len(p.relayState.trusteeBitMap) == p.relayState.nTrustees) { - p.findDisruptor() + var pred_array []proof.Predicate + suite := config.CryptoSuite + for i := 1; i < p.relayState.nTrustees; i++ { + i_string := strconv.Itoa(i) + pred_array = append(pred_array, proof.Rep("T"+i_string, "t"+i_string, "B")) + } + pred := proof.And(pred_array...) + verifier := pred.Verifier(suite, msg.Pval) + err := proof.HashVerify(suite, "DISRUPTION", verifier, msg.NIZK) + if err != nil { + log.Fatal("Proof failed to verify: ") } + log.Lvl3("Proof verified.") + + p.relayState.trusteeBitMap[msg.TrusteeID] = msg.Bits + result := p.compareBits(msg.TrusteeID, msg.Bits, p.relayState.CiphertextsHistoryTrustees) + if !result { + log.Fatal("Disruption Phase 1: Disruptor is Trustee", msg.TrusteeID, ".") + } else if (len(p.relayState.clientBitMap) == p.relayState.nClients) && (len(p.relayState.trusteeBitMap) == p.relayState.nTrustees) { + log.Lvl1("Disruption Phase 1: Trustee", msg.TrusteeID, ", is consistent with itself, checking mismatches with all clients...") + mismatch := p.checkMismatchingPairs() + if mismatch { + toClient := &net.REL_ALL_REVEAL_SHARED_SECRETS{ + EntityID: p.relayState.blamingData.TrusteeID, + } + toTrustee := &net.REL_ALL_REVEAL_SHARED_SECRETS{ + EntityID: p.relayState.blamingData.ClientID, + } + p.messageSender.SendToTrusteeWithLog(p.relayState.blamingData.ClientID, toTrustee, "") + p.messageSender.SendToClientWithLog(p.relayState.blamingData.TrusteeID, toClient, "") + } else { + log.Fatal("Disruption Phase 2: No mismatching pairs ? this should never occur.") + } + } + return nil } /* -findDisruptor is called when we received all the bits from clients and trustees, we must find a mismatch -*/ -func (p *PriFiLibRelayInstance) findDisruptor() error { - - for clientID, val := range p.relayState.clientBitMap { - for trusteeID, values := range p.relayState.trusteeBitMap { - if val[trusteeID] != values[clientID] { - log.Lvl1("Found difference between client ", clientID, " and trustee ", trusteeID) - - // message to trustee j and client i to reveal secrets - p.relayState.blamingData[2] = clientID - p.relayState.blamingData[3] = val[trusteeID] - p.relayState.blamingData[4] = trusteeID - p.relayState.blamingData[5] = values[clientID] - toSend := &net.REL_ALL_DISRUPTION_SECRET{ - UserID: clientID} - p.messageSender.SendToTrustee(trusteeID, toSend) - toSend2 := &net.REL_ALL_DISRUPTION_SECRET{ - UserID: trusteeID} - p.messageSender.SendToClient(clientID, toSend2) - return nil +* Auxiliary function that does the check of the bits revealed with the bit in the disruptive position. + */ +func (p *PriFiLibRelayInstance) compareBits(id int, bits map[int]int, CiphertextsHistory map[int32]map[int32][]byte) bool { + round := p.relayState.blamingData.RoundID + bitPosition := p.relayState.blamingData.BitPos + bytePosition := bitPosition/8 + 9 // LB->CV: why + 9 ? avoid magic numbers :) + + log.Lvl2("Disruption: comparing", bits, "with", CiphertextsHistory[int32(id)][int32(round)]) + + byteToGet := CiphertextsHistory[int32(id)][int32(round)][bytePosition] + log.Lvl1("CARLOS: BYTE", byteToGet) + bitInBytePosition := (8-bitPosition%8)%8 - 1 + mask := byte(1 << uint(bitInBytePosition)) + result := 0 + for _, bit := range bits { + result ^= bit + } + bytePreviousResult := mask & byteToGet + bitPreviousResult := 0 + if bytePreviousResult != 0 { + bitPreviousResult = 1 + } + + return (result == bitPreviousResult) +} + +/* +* Once the relay have received all the bits revealed and all match the bit in the disruptive position, +* the relay checks the bits between pairsof trustees and clients. +* When a mismatch is found, the Reveal secret message is called to the client and trustee. + */ +func (p *PriFiLibRelayInstance) checkMismatchingPairs() bool { + for clientID, clientBits := range p.relayState.clientBitMap { + for trusteeID, clientBit := range clientBits { + trusteeBit := p.relayState.trusteeBitMap[trusteeID][clientID] + if clientBit != trusteeBit { + log.Error("Disruption Phase 2: mismatch between trustee", trusteeID, "and client", clientID) + p.relayState.blamingData.ClientID = clientID + p.relayState.blamingData.ClientBitRevealed = clientBit + p.relayState.blamingData.TrusteeID = trusteeID + p.relayState.blamingData.TrusteeBitRevealed = trusteeBit + return true } } } - log.Lvl1("Found no differences in revealed bits") - return nil + return false } /* -Received_TRU_REL_SECRET handles TRU_REL_SECRET messages +Received_TRU_REL_SHARED_SECRETS handles TRU_REL_SECRET messages Check the NIZK, if correct regenerate the cipher up to the disrupted round and check if this trustee is the disruptor */ -func (p *PriFiLibRelayInstance) Received_TRU_REL_SECRET(msg net.TRU_REL_DISRUPTION_SECRET) error { +func (p *PriFiLibRelayInstance) Received_TRU_REL_SHARED_SECRETS(msg net.TRU_REL_SHARED_SECRET) error { + log.Lvl1("Disruption Phase 2: Received shared secret from Trustee", msg.TrusteeID, "for client", msg.ClientID, "value", msg.Secret) + + M := "SHAREDKEY" + X := make([]kyber.Point, 1) + X[0] = p.relayState.trustees[msg.TrusteeID].PublicKey + preds := make([]proof.Predicate, len(X)) + for i := range X { + name := fmt.Sprintf("X[%d]", i) // "X[0]","X[1]",... + msg.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 + suite := config.CryptoSuite + // Verify the signature + verifier := pred.Verifier(suite, msg.Pub) + err := proof.HashVerify(suite, M, verifier, msg.NIZK) + if err != nil { + log.Error("signature failed to verify: ", err) + } + log.Lvl3("Linkable Ring Signature verified.") + val := p.replayRounds(msg.Secret) - if val != p.relayState.blamingData[5] { - log.Lvl1("Trustee ", p.relayState.blamingData[4], " lied and is considered a disruptor") + if val != p.relayState.blamingData.TrusteeBitRevealed { + log.Fatal("Disruption Phase 2: Disruptor is Trustee", msg.TrusteeID, ".") + } else { + log.Lvl1("Disruption Phase 2: Trustee", msg.TrusteeID, "didn't lie, so it should be Client", msg.ClientID, ".") } return nil } /* -Received_CLI_REL_SECRET handles CLI_REL_SECRET messages +Received_CLI_REL_SHARED_SECRET handles CLI_REL_SECRET messages Check the NIZK, if correct regenerate the cipher up to the disrupted round and check if this client is the disruptor */ -func (p *PriFiLibRelayInstance) Received_CLI_REL_SECRET(msg net.CLI_REL_DISRUPTION_SECRET) error { +func (p *PriFiLibRelayInstance) Received_CLI_REL_SHARED_SECRET(msg net.CLI_REL_SHARED_SECRET) error { + log.Lvl1("Disruption Phase 2: Received shared secret from Client", msg.ClientID, "for Trustee", msg.TrusteeID, "value", msg.Secret) + + M := "SHAREDKEY" + X := make([]kyber.Point, 1) + X[0] = p.relayState.trustees[msg.TrusteeID].PublicKey + preds := make([]proof.Predicate, len(X)) + for i := range X { + name := fmt.Sprintf("X[%d]", i) // "X[0]","X[1]",... + msg.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 + suite := config.CryptoSuite + // Verify the signature + verifier := pred.Verifier(suite, msg.Pub) + err := proof.HashVerify(suite, M, verifier, msg.NIZK) + if err != nil { + log.Error("signature failed to verify: ", err) + } + log.Lvl3("Linkable Ring Signature verified.") + val := p.replayRounds(msg.Secret) - if val != p.relayState.blamingData[3] { - log.Lvl1("Client ", p.relayState.blamingData[2], " lied and is considered a disruptor") + if val != p.relayState.blamingData.ClientBitRevealed { + log.Fatal("Disruption Phase 2: Disruptor is Client", msg.ClientID, ".") + } else { + log.Lvl1("Disruption Phase 2: Client", msg.ClientID, "didn't lie, so it should be Client", msg.TrusteeID, ".") } return nil } @@ -122,35 +293,37 @@ func (p *PriFiLibRelayInstance) Received_CLI_REL_SECRET(msg net.CLI_REL_DISRUPTI replayRounds takes the secret revealed by a user and recomputes until the disrupted bit */ func (p *PriFiLibRelayInstance) replayRounds(secret kyber.Point) int { - /* - bytes, err := secret.MarshalBinary() - if err != nil { - log.Fatal("Could not marshal point !") - } - roundID := p.relayState.blamingData[0] - sharedPRNG := config.CryptoSuite.XOF(bytes) - key := make([]byte, config.CryptoSuite.XOF(nil).KeySize()) - sharedPRNG.Partial(key, key, nil) - dcCipher := config.CryptoSuite.XOF(key) - - for i := 0; i < roundID; i++ { - //discard crypto material - dst := make([]byte, p.relayState.PayloadSize) - dcCipher.Read(dst) - } + seed, err := secret.MarshalBinary() + if err != nil { + log.Fatal("Could not extract data from shared key", err) + } + sharedPRNG := config.CryptoSuite.XOF(seed) - dst := make([]byte, p.relayState.PayloadSize) - dcCipher.Read(dst) - bitPos := p.relayState.blamingData[0] - m := float64(bitPos) / float64(8) - m = math.Floor(m) - m2 := int(m) - n := bitPos % 8 - mask := byte(1 << uint8(n)) - if (dst[m2] & mask) == 0 { - return 0 - } - */ - log.Fatal("not implemented") - return 1 + round := int32(0) + disruptive_round := p.relayState.blamingData.RoundID + for round < disruptive_round { + + dummy := make([]byte, p.relayState.DCNet.DCNetPayloadSize) + sharedPRNG.XORKeyStream(dummy, dummy) + round++ + + } + + p_ij := make([]byte, p.relayState.DCNet.DCNetPayloadSize) + sharedPRNG.XORKeyStream(p_ij, p_ij) + + var rtn int + + bitPosition := p.relayState.blamingData.BitPos + bytePosition := int(bitPosition/8) + 1 + byte_toGet := p_ij[bytePosition] + bitInByte := (8-bitPosition%8)%8 - 1 + mask := byte(1 << uint(bitInByte)) + if (byte_toGet & mask) == 0 { + rtn = 0 + } else { + rtn = 1 + } + + return rtn } diff --git a/prifi-lib/relay/init.go b/prifi-lib/relay/init.go index 396530ad1..8dc23e947 100644 --- a/prifi-lib/relay/init.go +++ b/prifi-lib/relay/init.go @@ -118,6 +118,17 @@ type NodeRepresentation struct { EphemeralPublicKey kyber.Point } +// BlamingData is a struct used in the blame phase of the disruption protection. +// [round#, bitPos, clientID, bitRevealed, trusteeID, bitRevealed] +type BlamingData struct { + RoundID int32 + BitPos int + ClientID int + ClientBitRevealed int + TrusteeID int + TrusteeBitRevealed int +} + // RelayState contains the mutable state of the relay. type RelayState struct { DCNet *dcnet.DCNetEntity @@ -126,6 +137,7 @@ type RelayState struct { neffShuffle *scheduler.NeffShuffleRelay currentState int16 DataForClients chan []byte // VPN / SOCKS should put data there ! + HashOfLastUpstreamMessage [32]byte PriorityDataForClients chan []byte DataFromDCNet chan []byte // VPN / SOCKS should read data from there ! DataOutputEnabled bool // If FALSE, nothing will be written to DataFromDCNet @@ -171,9 +183,18 @@ type RelayState struct { processingLock sync.Mutex // either we treat a message, or a timeout, never both //disruption protection - clientBitMap map[int]map[int]int - trusteeBitMap map[int]map[int]int - blamingData []int //[round#, bitPos, clientID, bitRevealed, trusteeID, bitRevealed] + LastMessageOfClients map[int32][]byte + BEchoFlags map[int32]byte + CiphertextsHistoryTrustees map[int32]map[int32][]byte + CiphertextsHistoryClients map[int32]map[int32][]byte + DisruptionReveal bool + clientBitMap map[int]map[int]int + trusteeBitMap map[int]map[int]int + blamingData BlamingData + EphemeralPublicKeys []kyber.Point + + //disruption testing + ForceDisruptionSinceRound3 bool //Used for verifiable DC-net, part of the dcnet.old/owned.go VerifiableDCNetKeys [][]byte @@ -188,7 +209,6 @@ func (p *PriFiLibRelayInstance) ReceivedMessage(msg interface{}) error { defer p.relayState.processingLock.Unlock() var err error - switch typedMsg := msg.(type) { case net.ALL_ALL_PARAMETERS: if typedMsg.ForceParams || p.stateMachine.AssertState("BEFORE_INIT") { @@ -200,6 +220,22 @@ func (p *PriFiLibRelayInstance) ReceivedMessage(msg interface{}) error { if p.stateMachine.AssertState("COMMUNICATING") { err = p.Received_CLI_REL_UPSTREAM_DATA(typedMsg) } + case net.CLI_REL_DISRUPTION_REVEAL: + if p.stateMachine.AssertState("COMMUNICATING") { + err = p.Received_CLI_REL_DISRUPTION_REVEAL(typedMsg) + } + case net.TRU_REL_DISRUPTION_REVEAL: + if p.stateMachine.AssertState("COMMUNICATING") { + err = p.Received_TRU_REL_DISRUPTION_REVEAL(typedMsg) + } + case net.CLI_REL_SHARED_SECRET: + if p.stateMachine.AssertState("COMMUNICATING") { + err = p.Received_CLI_REL_SHARED_SECRET(typedMsg) + } + case net.TRU_REL_SHARED_SECRET: + if p.stateMachine.AssertState("COMMUNICATING") { + err = p.Received_TRU_REL_SHARED_SECRETS(typedMsg) + } case net.CLI_REL_OPENCLOSED_DATA: if p.stateMachine.AssertState("COMMUNICATING") { err = p.Received_CLI_REL_OPENCLOSED_DATA(typedMsg) @@ -224,6 +260,10 @@ func (p *PriFiLibRelayInstance) ReceivedMessage(msg interface{}) error { if p.stateMachine.AssertState("COLLECTING_SHUFFLE_SIGNATURES") { err = p.Received_TRU_REL_SHUFFLE_SIG(typedMsg) } + case net.CLI_REL_DISRUPTION_BLAME: + if p.stateMachine.AssertState("COMMUNICATING") { + err = p.Received_CLI_REL_DISRUPTION_BLAME(typedMsg) + } default: err = errors.New("Unrecognized message, type" + reflect.TypeOf(msg).String()) } diff --git a/prifi-lib/relay/relay.go b/prifi-lib/relay/relay.go index 600563ad7..af1ecfb7e 100644 --- a/prifi-lib/relay/relay.go +++ b/prifi-lib/relay/relay.go @@ -107,6 +107,7 @@ func (p *PriFiLibRelayInstance) Received_ALL_ALL_PARAMETERS(msg net.ALL_ALL_PARA trusteeCacheLowBound := msg.IntValueOrElse("RelayTrusteeCacheLowBound", p.relayState.TrusteeCacheLowBound) trusteeCacheHighBound := msg.IntValueOrElse("RelayTrusteeCacheHighBound", p.relayState.TrusteeCacheHighBound) equivocationProtectionEnabled := msg.BoolValueOrElse("EquivocationProtectionEnabled", p.relayState.EquivocationProtectionEnabled) + ForceDisruptionSinceRound3 := msg.BoolValueOrElse("ForceDisruptionSinceRound3", false) if payloadSize < 1 { return errors.New("payloadSize cannot be 0") @@ -134,6 +135,7 @@ func (p *PriFiLibRelayInstance) Received_ALL_ALL_PARAMETERS(msg net.ALL_ALL_PARA p.relayState.TrusteeCacheLowBound = trusteeCacheLowBound p.relayState.TrusteeCacheHighBound = trusteeCacheHighBound p.relayState.EquivocationProtectionEnabled = equivocationProtectionEnabled + p.relayState.ForceDisruptionSinceRound3 = ForceDisruptionSinceRound3 p.relayState.MessageHistory = config.CryptoSuite.XOF([]byte("init")) //any non-nil, non-empty, constant array p.relayState.VerifiableDCNetKeys = make([][]byte, nTrustees) p.relayState.nVkeysCollected = 0 @@ -143,9 +145,18 @@ func (p *PriFiLibRelayInstance) Received_ALL_ALL_PARAMETERS(msg net.ALL_ALL_PARA p.relayState.DisruptionProtectionEnabled = disruptionProtection p.relayState.clientBitMap = make(map[int]map[int]int) p.relayState.trusteeBitMap = make(map[int]map[int]int) - p.relayState.blamingData = make([]int, 6) p.relayState.OpenClosedSlotsRequestsRoundID = make(map[int32]bool) - + p.relayState.LastMessageOfClients = make(map[int32][]byte) + p.relayState.BEchoFlags = make(map[int32]byte) + p.relayState.CiphertextsHistoryTrustees = make(map[int32]map[int32][]byte) + p.relayState.CiphertextsHistoryClients = make(map[int32]map[int32][]byte) + //CV->LB: Is this the proper way to initialize this? + for i := int32(0); i < int32(nClients); i++ { + p.relayState.CiphertextsHistoryClients[i] = make(map[int32][]byte) + } + for j := int32(0); j < int32(nTrustees); j++ { + p.relayState.CiphertextsHistoryTrustees[j] = make(map[int32][]byte) + } switch dcNetType { case "Verifiable": panic("Verifiable DCNet not implemented yet") @@ -218,6 +229,12 @@ If we finished a round (we had collected all data, and called DecodeCell()), we Either we send something from the SOCKS/VPN buffer, or we answer the latency-test message if we received any, or we send 1 bit. */ func (p *PriFiLibRelayInstance) Received_CLI_REL_UPSTREAM_DATA(msg net.CLI_REL_UPSTREAM_DATA) error { + // CV-LB: I am not sure if this is a good programing practice... + if p.relayState.CiphertextsHistoryClients[int32(msg.ClientID)] == nil { + p.relayState.CiphertextsHistoryClients[int32(msg.ClientID)] = make(map[int32][]byte) + } + p.relayState.CiphertextsHistoryClients[int32(msg.ClientID)][msg.RoundID] = msg.Data + //CARLOS TODO: CLEAN HISTORY p.relayState.roundManager.AddClientCipher(msg.RoundID, msg.ClientID, msg.Data) if p.relayState.roundManager.HasAllCiphersForCurrentRound() { p.upstreamPhase1_processCiphers(true) @@ -232,6 +249,11 @@ If it's for this round, we call decode on it, and remember we received it. If for a future round we need to Buffer it. */ func (p *PriFiLibRelayInstance) Received_TRU_REL_DC_CIPHER(msg net.TRU_REL_DC_CIPHER) error { + if p.relayState.CiphertextsHistoryTrustees[int32(msg.TrusteeID)] == nil { + p.relayState.CiphertextsHistoryTrustees[int32(msg.TrusteeID)] = make(map[int32][]byte) + } + p.relayState.CiphertextsHistoryTrustees[int32(msg.TrusteeID)][msg.RoundID] = msg.Data + //CARLOS TODO: CLEAN HISTORY p.relayState.roundManager.AddTrusteeCipher(msg.RoundID, msg.TrusteeID, msg.Data) if p.relayState.roundManager.HasAllCiphersForCurrentRound() { p.upstreamPhase1_processCiphers(true) @@ -321,7 +343,7 @@ func (p *PriFiLibRelayInstance) upstreamPhase2a_extractOCMap(roundID int32) erro } //here we have the plaintext map - openClosedData := p.relayState.DCNet.DecodeCell() + openClosedData, _ := p.relayState.DCNet.DecodeCell(true) //compute the map newSchedule := p.relayState.slotScheduler.Relay_ComputeFinalSchedule(openClosedData, p.relayState.nClients) @@ -366,26 +388,76 @@ func (p *PriFiLibRelayInstance) upstreamPhase2b_extractPayload() error { for _, s := range trusteesSlices { p.relayState.DCNet.DecodeTrustee(roundID, s) } - upstreamPlaintext := p.relayState.DCNet.DecodeCell() + upstreamPlaintext, ciphertext := p.relayState.DCNet.DecodeCell(false) + if p.relayState.EquivocationProtectionEnabled && p.relayState.DisruptionProtectionEnabled { + // Generating and storing the hash from the payload + p.relayState.HashOfLastUpstreamMessage = sha256.Sum256([]byte(ciphertext)) + p.relayState.LastMessageOfClients[roundID] = ciphertext + log.Lvl1("CARLOS: HASING", ciphertext, "HASH", p.relayState.HashOfLastUpstreamMessage) + } p.relayState.bitrateStatistics.AddUpstreamCell(int64(len(upstreamPlaintext))) - //disruption-protection if p.relayState.DisruptionProtectionEnabled { - log.Lvl3("Verifying HMAC for disruption protection") - hmac := upstreamPlaintext[0:32] - upstreamPlaintext = upstreamPlaintext[32:] + var b_echo_last byte + b_echo_last = upstreamPlaintext[0] + p.relayState.BEchoFlags[roundID] = b_echo_last + p.relayState.DisruptionReveal = false + previousRound := roundID - int32(p.relayState.nClients) + + if b_echo_last == 1 { + if len(upstreamPlaintext) > 13 && string(upstreamPlaintext[1:6]) == "BLAME" { + log.Error("Detected a BLAME request!") + + blameRoundID := int32(binary.BigEndian.Uint32(upstreamPlaintext[6:10])) + blameBitPosition := int(binary.BigEndian.Uint32(upstreamPlaintext[10:14])) - clientID := -1 // todo loop with the schedule - valid := ValidateHmac256(upstreamPlaintext, hmac, clientID) + _ = blameRoundID // TODO: This should be used insted of "previousRound-p.relayState.nClients" + blameRoundID = previousRound - int32(p.relayState.nClients) - if !valid { - // start blame - log.Error("Warning: Disruption Protection check failed") + log.Error("Disruption: Going into Blame phase 1. Round:", blameRoundID, ", bit position:", blameBitPosition) + + p.relayState.DisruptionReveal = true + + p.relayState.blamingData.RoundID = blameRoundID + p.relayState.blamingData.BitPos = blameBitPosition + + // Broadcast Blame phase 1 + toSend := &net.REL_ALL_DISRUPTION_REVEAL{ + RoundID: int32(p.relayState.blamingData.RoundID), + BitPos: p.relayState.blamingData.BitPos, + } + for j := 0; j < p.relayState.nClients; j++ { + p.messageSender.SendToClientWithLog(j, toSend, "") + } + for j := 0; j < p.relayState.nTrustees; j++ { + p.messageSender.SendToTrusteeWithLog(j, toSend, "") + } + + } else { + log.Lvl1("b_echo_last=", b_echo_last, "(current round:", roundID, ")") + } + } + upstreamPlaintext = upstreamPlaintext[1:] + if !p.relayState.EquivocationProtectionEnabled { + // Saving in history + p.relayState.LastMessageOfClients[roundID] = upstreamPlaintext + } + + // CARLOS TODO: Clean the lastmessageofclients map + + //TEST + if p.relayState.roundManager.CurrentRound() == 100 { + //upstreamPlaintext[3] = 8 + } + + if !p.relayState.EquivocationProtectionEnabled { + // Generating and storing the hash from the payload + p.relayState.HashOfLastUpstreamMessage = sha256.Sum256([]byte(upstreamPlaintext)) } - } + } log.Lvl4("Decoded cell is", upstreamPlaintext) // check if we have a latency test message, or a pcap meta message @@ -444,7 +516,11 @@ func (p *PriFiLibRelayInstance) upstreamPhase2b_extractPayload() error { // verify that the decoded payload has the correct size expectedSize := p.relayState.PayloadSize if p.relayState.DisruptionProtectionEnabled { - expectedSize -= 32 + // One less because of the b_echo_last flag + expectedSize-- + } + if p.relayState.EquivocationProtectionEnabled { + expectedSize -= 16 } if len(upstreamPlaintext) != expectedSize { e := "Relay : DecodeCell produced wrong-size payload, " + strconv.Itoa(len(upstreamPlaintext)) + "!=" + strconv.Itoa(p.relayState.PayloadSize) @@ -544,6 +620,17 @@ func (p *PriFiLibRelayInstance) downstreamPhase1_openRoundAndSendData() error { } } + if p.relayState.DisruptionProtectionEnabled { + // Check if the b_echo_last flag from the client was set. + // If so, send the previous round message + if p.relayState.BEchoFlags[p.relayState.roundManager.lastRoundClosed] == 1 { + previousRound := p.relayState.roundManager.lastRoundClosed - int32(p.relayState.nClients) + downstreamCellContent = p.relayState.LastMessageOfClients[previousRound] + log.Lvl1("b_echo_last=1 on round", p.relayState.roundManager.lastRoundClosed, "retransmitting upstream of round", previousRound) + log.Lvl1(downstreamCellContent) + } + } + // if we want to use dummy data down, pad to the correct size if p.relayState.UseDummyDataDown && len(downstreamCellContent) < p.relayState.DownstreamCellSize { data := make([]byte, p.relayState.DownstreamCellSize) @@ -580,11 +667,12 @@ func (p *PriFiLibRelayInstance) downstreamPhase1_openRoundAndSendData() error { } toSend := &net.REL_CLI_DOWNSTREAM_DATA{ - RoundID: nextDownstreamRoundID, - OwnershipID: nextOwner, - Data: downstreamCellContent, - FlagResync: flagResync, - FlagOpenClosedRequest: flagOpenClosedRequest} + RoundID: nextDownstreamRoundID, + OwnershipID: nextOwner, + HashOfPreviousUpstreamData: p.relayState.HashOfLastUpstreamMessage[:], + Data: downstreamCellContent, + FlagResync: flagResync, + FlagOpenClosedRequest: flagOpenClosedRequest} if roundOpened, _ := p.relayState.roundManager.currentRound(); !roundOpened { //prepare for the next round (this empties the dc-net buffer, making them ready for a new round) @@ -655,6 +743,7 @@ func (p *PriFiLibRelayInstance) Received_TRU_REL_TELL_PK(msg net.TRU_REL_TELL_PK toSend.Add("DCNetType", p.relayState.dcNetType) toSend.Add("DisruptionProtectionEnabled", p.relayState.DisruptionProtectionEnabled) toSend.Add("EquivocationProtectionEnabled", p.relayState.EquivocationProtectionEnabled) + toSend.Add("ForceDisruptionSinceRound3", p.relayState.ForceDisruptionSinceRound3) toSend.TrusteesPks = trusteesPk // Send those parameters to all clients @@ -728,7 +817,7 @@ func (p *PriFiLibRelayInstance) Received_TRU_REL_TELL_NEW_BASE_AND_EPH_PKS(msg n p.relayState.VerifiableDCNetKeys[p.relayState.nVkeysCollected] = msg.VerifiableDCNetKey p.relayState.nVkeysCollected++ - + p.relayState.EphemeralPublicKeys = msg.NewEphPks done, err := p.relayState.neffShuffle.ReceivedShuffleFromTrustee(msg.NewBase, msg.NewEphPks, msg.Proof) if err != nil { e := "Relay : error in p.relayState.neffShuffle.ReceivedShuffleFromTrustee " + err.Error() @@ -805,7 +894,6 @@ func (p *PriFiLibRelayInstance) Received_TRU_REL_SHUFFLE_SIG(msg net.TRU_REL_SHU log.Error(e) return errors.New(e) } - // if we have all the signatures if done { trusteesPks := make([]kyber.Point, p.relayState.nTrustees) diff --git a/prifi-lib/relay/relay_test.go b/prifi-lib/relay/relay_test.go index 2006fe4d9..193041fcb 100644 --- a/prifi-lib/relay/relay_test.go +++ b/prifi-lib/relay/relay_test.go @@ -450,7 +450,7 @@ func TestRelayRun1(t *testing.T) { } func TestRelayRun2(t *testing.T) { - + //TODO: HASH CHECKING timeoutHandler := func(clients, trustees []int) { log.Error(clients, trustees) } resultChan := make(chan interface{}, 1) diff --git a/prifi-lib/trustee/disruption.go b/prifi-lib/trustee/disruption.go new file mode 100644 index 000000000..4ca1e7ae8 --- /dev/null +++ b/prifi-lib/trustee/disruption.go @@ -0,0 +1,112 @@ +package trustee + +import ( + "fmt" + "github.com/dedis/prifi/prifi-lib/config" + "github.com/dedis/prifi/prifi-lib/net" + "go.dedis.ch/kyber" + "go.dedis.ch/kyber/proof" + "gopkg.in/dedis/onet.v2/log" + "strconv" +) + +/* +* 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 *PriFiLibTrusteeInstance) 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.trusteeState.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...) + log.Lvl1("CARLOS EXPLODE: ", pred) + + prover := pred.Prover(suite, sval, pval, nil) + NIZK, _ := proof.HashProve(suite, "DISRUPTION", prover) + + verifier := pred.Verifier(suite, pval) + err := proof.HashVerify(suite, "DISRUPTION", verifier, NIZK) + if err != nil { + log.Error("EE Proof failed to verify: ") + } + log.Lvl1("EE Proof verified.") + toSend := &net.TRU_REL_DISRUPTION_REVEAL{ + TrusteeID: p.trusteeState.ID, + Bits: bitMap, + } + p.messageSender.SendToRelayWithLog(toSend, "") + log.Lvl1("Disruption: Sending previous round to relay (Round: ", msg.RoundID, ", bit position:", msg.BitPos, "), value", bitMap) + 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 *PriFiLibTrusteeInstance) 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 client", msg.EntityID) + // CARLOS 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.trusteeState.sharedSecrets[msg.EntityID] + // as a pseudorandom base point multiplied by our private key. + suite := config.CryptoSuite + X := make([]kyber.Point, 1) + X[0] = p.trusteeState.PublicKey + B := suite.Point().Base() //BACK + // Generate the proof predicate: an OR branch for each public key. + sec := map[string]kyber.Scalar{"x": p.trusteeState.privateKey} //BACK + pub := map[string]kyber.Point{"B": B, "BT": p.trusteeState.ClientPublicKeys[msg.EntityID], "T": p.trusteeState.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.TRU_REL_SHARED_SECRET{ + TrusteeID: p.trusteeState.ID, + ClientID: msg.EntityID, + Secret: secret, + NIZK: NIZK, + Pub: pub, + } + p.messageSender.SendToRelayWithLog(toSend, "Sent secret to relay") + log.Lvl1("Reveling secret with client", msg.EntityID) + return nil +} diff --git a/prifi-lib/trustee/init.go b/prifi-lib/trustee/init.go index 9d97c44eb..4669aaad3 100644 --- a/prifi-lib/trustee/init.go +++ b/prifi-lib/trustee/init.go @@ -127,13 +127,11 @@ func (p *PriFiLibTrusteeInstance) ReceivedMessage(msg interface{}) error { } case net.REL_ALL_DISRUPTION_REVEAL: if p.stateMachine.AssertState("READY") { - log.Fatal("not implemented") - //err = p.Received_REL_ALL_REVEAL(typedMsg) + err = p.Received_REL_ALL_DISRUPTION_REVEAL(typedMsg) } - case net.REL_ALL_DISRUPTION_SECRET: - if p.stateMachine.AssertState("BLAMING") { - log.Fatal("not implemented") - //err = p.Received_REL_ALL_SECRET(typedMsg) + case net.REL_ALL_REVEAL_SHARED_SECRETS: + if p.stateMachine.AssertState("READY") { + err = p.Received_REL_ALL_REVEAL_SHARED_SECRETS(typedMsg) } default: err = errors.New("Unrecognized message, type" + reflect.TypeOf(msg).String()) diff --git a/prifi-lib/trustee/trustee.go b/prifi-lib/trustee/trustee.go index 1ba3f0108..4e1d3f466 100644 --- a/prifi-lib/trustee/trustee.go +++ b/prifi-lib/trustee/trustee.go @@ -194,7 +194,6 @@ It returns the new round number (previous + 1). */ func sendData(p *PriFiLibTrusteeInstance, roundID int32) (int32, error) { data := p.trusteeState.DCNet.TrusteeEncodeForRound(roundID) - //send the data toSend := &net.TRU_REL_DC_CIPHER{ RoundID: roundID, @@ -290,33 +289,3 @@ func (p *PriFiLibTrusteeInstance) Received_REL_TRU_TELL_TRANSCRIPT(msg net.REL_T return nil } - -/* -Received_REL_ALL_REVEAL handles REL_ALL_REVEAL messages. -We send back one bit per client, from the shared cipher, at bitPos -*/ -/* -func (p *PriFiLibTrusteeInstance) Received_REL_ALL_REVEAL(msg net.REL_ALL_DISRUPTION_REVEAL) error { - p.stateMachine.ChangeState("BLAMING") - bits := p.trusteeState.DCNet.RevealBits(msg.RoundID, msg.BitPos, p.trusteeState.PayloadSize) - toSend := &net.TRU_REL_DISRUPTION_REVEAL{ - TrusteeID: p.trusteeState.ID, - Bits: bits} - p.messageSender.SendToRelayWithLog(toSend, "Revealed bits") - return nil -} -*/ - -/* -Received_REL_ALL_SECRET handles REL_ALL_SECRET messages. -We send back the shared secret with the indicated client -*/ -func (p *PriFiLibTrusteeInstance) Received_REL_ALL_SECRET(msg net.REL_ALL_DISRUPTION_SECRET) error { - - secret := p.trusteeState.sharedSecrets[msg.UserID] - toSend := &net.TRU_REL_DISRUPTION_SECRET{ - Secret: secret, - NIZK: make([]byte, 0)} - p.messageSender.SendToRelayWithLog(toSend, "Sent secret to relay") - return nil -} diff --git a/prifi.sh b/prifi.sh index 9cb2651ea..4c90c4256 100755 --- a/prifi.sh +++ b/prifi.sh @@ -13,7 +13,7 @@ # variables that you might change often dbg_lvl=3 # 1=less verbose, 3=more verbose. goes up to 5, but then prints the SDA's message (network framework) -try_use_real_identities="false" # if "true", will try to use "self-generated" public/private key as a replacement for the dummy keys +try_use_real_identities="false" # if "true", will try to use "self-generated" public/private key as a replacement for the dummy keys # we generated for you. It asks you if it does not find real keys. If false, will always use the dummy keys. colors="true" # if "false", the output of PriFi (and this script) will be in black-n-white diff --git a/sda/protocols/message_binders.go b/sda/protocols/message_binders.go index 0b0ef3869..b426516df 100644 --- a/sda/protocols/message_binders.go +++ b/sda/protocols/message_binders.go @@ -97,17 +97,17 @@ func (p *PriFiSDAProtocol) Received_TRU_REL_DISRUPTION_REVEAL(msg Struct_TRU_REL return p.prifiLibInstance.ReceivedMessage(msg.TRU_REL_DISRUPTION_REVEAL) } -// Received_REL_ALL_DISRUPTION_SECRET forward an REL_ALL_DISRUPTION_SECRET message to PriFi's lib +// Received_REL_ALL_REVEAL_SHARED_SECRETS forward an REL_ALL_REVEAL_SHARED_SECRETS message to PriFi's lib func (p *PriFiSDAProtocol) Received_REL_ALL_DISRUPTION_SECRET(msg Struct_REL_ALL_DISRUPTION_SECRET) error { - return p.prifiLibInstance.ReceivedMessage(msg.REL_ALL_DISRUPTION_SECRET) + return p.prifiLibInstance.ReceivedMessage(msg.REL_ALL_REVEAL_SHARED_SECRETS) } -// Received_CLI_REL_DISRUPTION_SECRET forward an CLI_REL_DISRUPTION_SECRET message to PriFi's lib +// Received_CLI_REL_DISRUPTION_SECRET forward an CLI_REL_SHARED_SECRET message to PriFi's lib func (p *PriFiSDAProtocol) Received_CLI_REL_DISRUPTION_SECRET(msg Struct_CLI_REL_DISRUPTION_SECRET) error { - return p.prifiLibInstance.ReceivedMessage(msg.CLI_REL_DISRUPTION_SECRET) + return p.prifiLibInstance.ReceivedMessage(msg.CLI_REL_SHARED_SECRET) } -// Received_TRU_REL_DISRUPTION_SECRET forward an TRU_REL_DISRUPTION_SECRET message to PriFi's lib +// Received_TRU_REL_DISRUPTION_SECRET forward an TRU_REL_SHARED_SECRET message to PriFi's lib func (p *PriFiSDAProtocol) Received_TRU_REL_DISRUPTION_SECRET(msg Struct_TRU_REL_DISRUPTION_SECRET) error { - return p.prifiLibInstance.ReceivedMessage(msg.TRU_REL_DISRUPTION_SECRET) + return p.prifiLibInstance.ReceivedMessage(msg.TRU_REL_SHARED_SECRET) } diff --git a/sda/protocols/messages.go b/sda/protocols/messages.go index 8ccf9b5c8..aa8938063 100644 --- a/sda/protocols/messages.go +++ b/sda/protocols/messages.go @@ -119,20 +119,20 @@ type Struct_TRU_REL_DISRUPTION_REVEAL struct { net.TRU_REL_DISRUPTION_REVEAL } -//Struct_REL_ALL_DISRUPTION_SECRET is a wrapper for REL_ALL_DISRUPTION_SECRET (but also contains a *onet.TreeNode) +//Struct_REL_ALL_DISRUPTION_SECRET is a wrapper for REL_ALL_REVEAL_SHARED_SECRETS (but also contains a *onet.TreeNode) type Struct_REL_ALL_DISRUPTION_SECRET struct { *onet.TreeNode - net.REL_ALL_DISRUPTION_SECRET + net.REL_ALL_REVEAL_SHARED_SECRETS } -//Struct_CLI_REL_DISRUPTION_SECRET is a wrapper for CLI_REL_DISRUPTION_SECRET (but also contains a *onet.TreeNode) +//Struct_CLI_REL_DISRUPTION_SECRET is a wrapper for CLI_REL_SHARED_SECRET (but also contains a *onet.TreeNode) type Struct_CLI_REL_DISRUPTION_SECRET struct { *onet.TreeNode - net.CLI_REL_DISRUPTION_SECRET + net.CLI_REL_SHARED_SECRET } -//Struct_TRU_REL_DISRUPTION_SECRET is a wrapper for TRU_REL_DISRUPTION_SECRET (but also contains a *onet.TreeNode) +//Struct_TRU_REL_DISRUPTION_SECRET is a wrapper for TRU_REL_SHARED_SECRET (but also contains a *onet.TreeNode) type Struct_TRU_REL_DISRUPTION_SECRET struct { *onet.TreeNode - net.TRU_REL_DISRUPTION_SECRET + net.TRU_REL_SHARED_SECRET } diff --git a/sda/protocols/prifi.go b/sda/protocols/prifi.go index 86c7cf523..f612017cf 100644 --- a/sda/protocols/prifi.go +++ b/sda/protocols/prifi.go @@ -66,6 +66,7 @@ type PrifiTomlConfig struct { RelayTrusteeCacheLowBound int RelayTrusteeCacheHighBound int VerboseIngressEgressServers bool + ForceDisruptionSinceRound3 bool } //PriFiSDAWrapperConfig is all the information the SDA-Protocols needs. It contains the network map of identities, our role, and the socks parameters if we are the corresponding role diff --git a/sda/protocols/protocol.go b/sda/protocols/protocol.go index fff954cc0..f69837c19 100644 --- a/sda/protocols/protocol.go +++ b/sda/protocols/protocol.go @@ -82,6 +82,7 @@ func (p *PriFiSDAProtocol) Start() error { msg.Add("RelayTrusteeCacheLowBound", p.config.Toml.RelayTrusteeCacheLowBound) msg.Add("RelayTrusteeCacheHighBound", p.config.Toml.RelayTrusteeCacheHighBound) msg.Add("EquivocationProtectionEnabled", p.config.Toml.EquivocationProtectionEnabled) + msg.Add("ForceDisruptionSinceRound3", p.config.Toml.ForceDisruptionSinceRound3) msg.ForceParams = true p.SendTo(p.TreeNode(), msg) @@ -134,9 +135,9 @@ func init() { network.RegisterMessage(net.REL_ALL_DISRUPTION_REVEAL{}) network.RegisterMessage(net.CLI_REL_DISRUPTION_REVEAL{}) network.RegisterMessage(net.TRU_REL_DISRUPTION_REVEAL{}) - network.RegisterMessage(net.REL_ALL_DISRUPTION_SECRET{}) - network.RegisterMessage(net.CLI_REL_DISRUPTION_SECRET{}) - network.RegisterMessage(net.TRU_REL_DISRUPTION_SECRET{}) + network.RegisterMessage(net.REL_ALL_REVEAL_SHARED_SECRETS{}) + network.RegisterMessage(net.CLI_REL_SHARED_SECRET{}) + network.RegisterMessage(net.TRU_REL_SHARED_SECRET{}) onet.GlobalProtocolRegister(ProtocolName, NewPriFiSDAWrapperProtocol) } diff --git a/socks/prifi-socks-server.go b/socks/prifi-socks-server.go index 862f4fc55..3280d0cf0 100755 --- a/socks/prifi-socks-server.go +++ b/socks/prifi-socks-server.go @@ -7,7 +7,7 @@ import ( "strconv" ) -const defaultBugLevel = 3 +const defaultBugLevel = 1 const defaultPort = 8090 var onetDebugLevels = []int{1, 2, 3, 4, 5} diff --git a/test.sh b/test.sh index c19b8b493..44e9dd119 100755 --- a/test.sh +++ b/test.sh @@ -10,7 +10,7 @@ # # ************************************ -# variables that you might change often +# variables that you might change often dbg_lvl=3 # 1=less verbose, 3=more verbose. goes up to 5, but then prints the SDA's message (network framework) colors="true" # if "false", the output of PriFi (and this script) will be in black-n-white