From a631f5c14f183c129f9743aebb35f53defae88f3 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Thu, 25 Apr 2024 15:44:42 +0200 Subject: [PATCH 01/15] add result message schema --- .../federation_result/federation_result.json | 5 ++++ protocol/query/method/message/data/data.json | 3 ++ .../message/data/dataFederationResult.json | 28 +++++++++++++++++++ protocol/test/main.js | 2 ++ protocol/test/main.test.js | 4 +++ 5 files changed, 42 insertions(+) create mode 100644 protocol/examples/messageData/federation_result/federation_result.json create mode 100644 protocol/query/method/message/data/dataFederationResult.json diff --git a/protocol/examples/messageData/federation_result/federation_result.json b/protocol/examples/messageData/federation_result/federation_result.json new file mode 100644 index 0000000000..1bf5bdfbb1 --- /dev/null +++ b/protocol/examples/messageData/federation_result/federation_result.json @@ -0,0 +1,5 @@ +{ + "object": "federation", + "action": "result", + "status": "success" +} diff --git a/protocol/query/method/message/data/data.json b/protocol/query/method/message/data/data.json index 0dceaba4d6..382d5eb1d0 100644 --- a/protocol/query/method/message/data/data.json +++ b/protocol/query/method/message/data/data.json @@ -64,6 +64,9 @@ { "$ref": "dataFederationChallenge.json" }, + { + "$ref": "dataFederationResult.json" + }, { "$ref": "dataWitnessMessage.json" }, diff --git a/protocol/query/method/message/data/dataFederationResult.json b/protocol/query/method/message/data/dataFederationResult.json new file mode 100644 index 0000000000..a4aa2d1439 --- /dev/null +++ b/protocol/query/method/message/data/dataFederationResult.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/query/method/message/data/dataFederationResult.json", + "description": "Sent by an server to a remote server, to inform them about the result of the authentication procedure", + "type": "object", + "properties": { + "object": { + "const": "federation" + }, + "action": { + "const": "result" + }, + "status": { + "type": "string", + "$comment": "status of the authentication attempt" + }, + "reason": { + "type": "string", + "$comment": "to be used in failures, describing the error that happened" + } + }, + "additionalProperties": false, + "required": [ + "object", + "action", + "status" + ] +} diff --git a/protocol/test/main.js b/protocol/test/main.js index 3075c2f29b..6a918a1b43 100644 --- a/protocol/test/main.js +++ b/protocol/test/main.js @@ -43,6 +43,7 @@ const message_data_federation_init_schema = require("../query/method/message/dat const message_data_federation_expect_schema = require("../query/method/message/data/dataFederationExpect.json") const message_data_federation_challenge_request_schema = require("../query/method/message/data/dataFederationChallengeRequest.json") const message_data_federation_challenge_schema = require("../query/method/message/data/dataFederationChallenge.json") +const message_data_federation_result_schema = require("../query/method/message/data/dataFederationResult.json") const message_data_chirp_add_schema = require("../query/method/message/data/dataAddChirp.json"); const message_data_chirp_notify_add_schema = require("../query/method/message/data/dataNotifyAddChirp.json"); @@ -112,6 +113,7 @@ ajv.addSchema([ message_data_federation_expect_schema, message_data_federation_challenge_request_schema, message_data_federation_challenge_schema, + message_data_federation_result_schema, message_data_chirp_notify_add_schema, message_data_chirp_add_schema, diff --git a/protocol/test/main.test.js b/protocol/test/main.test.js index 6ef0d13286..728da8d012 100644 --- a/protocol/test/main.test.js +++ b/protocol/test/main.test.js @@ -6,6 +6,7 @@ const ajv = require("./main"); const rootSchema = "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/jsonRPC.json"; + const messageDataSchema = "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/query/method/message/data/data.json"; @@ -263,6 +264,9 @@ test("message data: federation", () => { federation_challenge = require("../examples/messageData/federation_challenge/federation_challenge.json"); expect(federation_challenge).toBeValid(messageDataSchema); + federation_result = require("../examples/messageData/federation_result/federation_result.json"); + expect(federation_result).toBeValid(messageDataSchema); + }); test("message data: chirp", () => { From a02f78b2ccf24899a6808057dc6cb8e060bc5d50 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Mon, 29 Apr 2024 15:46:08 +0200 Subject: [PATCH 02/15] add federation result handling to be1 (WIP) --- be1-go/channel/federation/federation.go | 86 ++++++++++++++++++- be1-go/channel/federation/federation_test.go | 43 ++++++++++ .../message/messagedata/federation_result.go | 25 ++++++ be1-go/message/messagedata/mod.go | 1 + 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 be1-go/message/messagedata/federation_result.go diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index e40433aec6..163d816a83 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -138,6 +138,7 @@ func (c *Channel) NewFederationRegistry() registry.MessageRegistry { fedRegistry.Register(messagedata.FederationExpect{}, c.processFederationExpect) fedRegistry.Register(messagedata.FederationInit{}, c.processFederationInit) fedRegistry.Register(messagedata.FederationChallenge{}, c.processFederationChallenge) + fedRegistry.Register(messagedata.FederationResult{}, c.processFederationResult) return fedRegistry } @@ -237,6 +238,8 @@ func (c *Channel) processFederationInit(msg message.Message, c.remoteServer.Send(buf) + c.state = WaitResult + return nil } @@ -318,7 +321,55 @@ func (c *Channel) processFederationChallenge(msg message.Message, c.state = Connected c.remoteServer = s // Send Federation result to S1 - // c.remoteServer.Send(...) + + federationResultData := messagedata.FederationResult{ + Object: messagedata.FederationObject, + Action: messagedata.FederationActionResult, + Status: "success", + } + + dataBytes, err := json.Marshal(federationResultData) + if err != nil { + return xerrors.Errorf("failed to marshal federation result message data: %v", err) + } + + dataBase64 := base64.URLEncoding.EncodeToString(dataBytes) + signatureBytes, err := c.hub.Sign(dataBytes) + if err != nil { + return xerrors.Errorf("failed to sign federation result message: %v", err) + } + signatureBase64 := base64.URLEncoding.EncodeToString(signatureBytes) + + federationResultMsg := message.Message{ + Data: dataBase64, + Sender: c.hub.GetPubKeyServ().String(), + Signature: signatureBase64, + MessageID: messagedata.Hash(dataBase64, signatureBase64), + WitnessSignatures: []message.WitnessSignature{}, + } + + rpcMessage := method.Publish{ + Base: query.Base{ + JSONRPCBase: jsonrpc.JSONRPCBase{ + JSONRPC: "2.0", + }, + Method: "publish", + }, + + Params: struct { + Channel string `json:"channel"` + Message message.Message `json:"message"` + }{ + Channel: c.remoteChannel, + Message: federationResultMsg, + }, + } + buf, err := json.Marshal(&rpcMessage) + if err != nil { + return xerrors.Errorf("failed to marshal publish query: %v", err) + } + + c.remoteServer.Send(buf) return nil } @@ -424,3 +475,36 @@ func (c *Channel) processChallengeRequest(msg message.Message, return nil } + +func (c *Channel) processFederationResult(msg message.Message, + msgData interface{}, s socket.Socket) error { + _, ok := msgData.(*messagedata.FederationResult) + if !ok { + return xerrors.Errorf("message %v is not a federation#result message", + msgData) + } + + /* + This state should probably be set after sending the FederationInit message? + */ + //if c.state != WaitResult { + // return answer.NewInternalServerError(invalidStateError, c.state, msg) + //} + + var federationResult messagedata.FederationResult + + err := msg.UnmarshalData(&federationResult) + if err != nil { + c.state = None + return xerrors.Errorf("failed to unmarshal FederationResult data: %v", err) + } + + if federationResult.Status != "success" { + if len(federationResult.Reason) > 0 { + return xerrors.Errorf("failed to establish federated connection: %v", federationResult.Reason) + } + return xerrors.Errorf("failed to establish federated connection") + } + + return nil +} diff --git a/be1-go/channel/federation/federation_test.go b/be1-go/channel/federation/federation_test.go index 0f97396d2b..18c0e4f7c4 100644 --- a/be1-go/channel/federation/federation_test.go +++ b/be1-go/channel/federation/federation_test.go @@ -348,6 +348,49 @@ func Test_FederationInit(t *testing.T) { } +func Test_FederationResult(t *testing.T) { + organizerKeypair := generateKeyPair(t) + remoteOrganizerKeypair := generateKeyPair(t) + fakeHub, err := NewFakeHub("", organizerKeypair.public, nolog, nil) + require.NoError(t, err) + + fedChannel := NewChannel(localFedChannel, fakeHub, nolog, + organizerKeypair.publicKey) + + remotePublicKeyBytes, err := remoteOrganizerKeypair.public.MarshalBinary() + require.NoError(t, err) + signedRemotePublicKey, err := schnorr.Sign(crypto.Suite, organizerKeypair.private, remotePublicKeyBytes) + require.NoError(t, err) + + signedRemotePublicKeyBase64 := base64.URLEncoding.EncodeToString(signedRemotePublicKey) + + challengeFile := filepath.Join(relativeMsgDataExamplePath, + "federation_challenge", + "federation_challenge.json") + challengeBytes, err := os.ReadFile(challengeFile) + require.NoError(t, err) + signedChallengeBytes, err := schnorr.Sign(crypto.Suite, organizerKeypair.private, challengeBytes) + require.NoError(t, err) + signedChallengeBase64 := base64.URLEncoding.EncodeToString(signedChallengeBytes) + + t.Log(signedRemotePublicKeyBase64) + t.Log(signedChallengeBase64) + t.Log() + t.Log() + + federationResultData := messagedata.FederationResult{ + Object: messagedata.FederationObject, + Action: messagedata.FederationActionResult, + Status: "success", + } + resultMsg := generateMessage(t, organizerKeypair, federationResultData) + publishMsg := generatePublish(t, localFedChannel, resultMsg) + socket := &fakeSocket{id: "sockSocket"} + + err = fedChannel.Publish(publishMsg, socket) + require.NoError(t, err) +} + // ----------------------------------------------------------------------------- // Utility functions diff --git a/be1-go/message/messagedata/federation_result.go b/be1-go/message/messagedata/federation_result.go new file mode 100644 index 0000000000..ac7d39a026 --- /dev/null +++ b/be1-go/message/messagedata/federation_result.go @@ -0,0 +1,25 @@ +package messagedata + +// FederationResult defines a message data +type FederationResult struct { + Object string `json:"object"` + Action string `json:"action"` + + Status string `json:"status"` + Reason string `json:"reason,omitempty"` +} + +// GetObject implements MessageData +func (FederationResult) GetObject() string { + return FederationObject +} + +// GetAction implements MessageData +func (FederationResult) GetAction() string { + return FederationActionResult +} + +// NewEmpty implements MessageData +func (FederationResult) NewEmpty() MessageData { + return &FederationResult{} +} diff --git a/be1-go/message/messagedata/mod.go b/be1-go/message/messagedata/mod.go index b836ecbdb1..7fbc82e939 100644 --- a/be1-go/message/messagedata/mod.go +++ b/be1-go/message/messagedata/mod.go @@ -54,6 +54,7 @@ const ( FederationActionChallenge = "challenge" FederationActionInit = "init" FederationActionExpect = "expect" + FederationActionResult = "result" ChirpObject = "chirp" ChirpActionAdd = "add" From 679ab2fb775fc80e3040876f01e3e5c2202b9f30 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Mon, 29 Apr 2024 17:33:50 +0200 Subject: [PATCH 03/15] adapt json schema of federation_result --- .../federation_result/federation_result.json | 12 ++++ .../message/data/dataFederationResult.json | 70 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 protocol/examples/messageData/federation_result/federation_result.json create mode 100644 protocol/query/method/message/data/dataFederationResult.json diff --git a/protocol/examples/messageData/federation_result/federation_result.json b/protocol/examples/messageData/federation_result/federation_result.json new file mode 100644 index 0000000000..f4bef67148 --- /dev/null +++ b/protocol/examples/messageData/federation_result/federation_result.json @@ -0,0 +1,12 @@ +{ + "object": "federation", + "action": "result", + "status": "success", + "challenge": { + "data": "eyJvYmplY3QiOiJmZWRlcmF0aW9uIiwiYWN0aW9uIjoiY2hhbGxlbmdlIiwidmFsdWUiOiJlYmEzZTI0ZWZjZDBiNTNmYTY5OTA4YmFkNWQxY2I2OTlkNzk4MGQ5MzEwOWRhMGIyYmZkNTAzN2MyYzg5ZWUwIiwidGltZXN0YW1wIjoxNzEzMzg1NTY4fQ==", + "sender": "zXgzQaa_NpUe-v0Zk_4q8k184ohQ5nTQhBDKgncHzq4=", + "signature": "BILYwYkT5tOBL4rCD7yvhBkhAYqRXOI3ajQ2uJ1gAk-g6nRc38vMMnlHShuNCQ3dQFXYZPn37cCFelhWGjY8Bg==", + "message_id": "sD_PdryBuOr14_65h8L-e1lzdQpDWxUAngtu1uwqgEI=", + "witness_signatures": [] + } +} diff --git a/protocol/query/method/message/data/dataFederationResult.json b/protocol/query/method/message/data/dataFederationResult.json new file mode 100644 index 0000000000..4f3d7ff786 --- /dev/null +++ b/protocol/query/method/message/data/dataFederationResult.json @@ -0,0 +1,70 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/query/method/message/data/dataFederationResult.json", + "description": "Sent by an server to a remote server, to inform them about the result of the authentication procedure", + "type": "object", + "oneOf": [ + { + "type": "object", + "properties": { + "object": { + "const": "federation" + }, + "action": { + "const": "result" + }, + "status": { + "type": "string", + "$comment": "status of the authentication attempt" + }, + "reason": { + "type": "string", + "$comment": "to be used in failures, describing the error that happened" + }, + "challenge": { + "$ref": "../message.json", + "$comment": "message/message containing a FederationChallenge data" + } + }, + "additionalProperties": false, + "required": [ + "object", + "action", + "status", + "challenge" + ] + }, + { + "type": "object", + "properties": { + "object": { + "const": "federation" + }, + "action": { + "const": "result" + }, + "status": { + "type": "string", + "$comment": "status of the authentication attempt" + }, + "public_key": { + "type": "string", + "contentEncoding": "base64", + "$comment": "public key of the remote organizer" + }, + "challenge": { + "$ref": "../message.json", + "$comment": "message/message containing a FederationChallenge data" + } + }, + "additionalProperties": false, + "required": [ + "object", + "action", + "status", + "public_key", + "challenge" + ] + } + ] +} From fc29ff790c31be89f51dda3a2513dc9fc7f944b0 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Tue, 30 Apr 2024 13:46:17 +0200 Subject: [PATCH 04/15] improvements in response to review --- .../messageData/federation_result/federation_result.json | 1 + protocol/query/method/message/data/data.json | 3 +++ protocol/query/method/message/data/dataFederationResult.json | 3 +++ protocol/test/main.js | 2 ++ protocol/test/main.test.js | 5 ++++- 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/protocol/examples/messageData/federation_result/federation_result.json b/protocol/examples/messageData/federation_result/federation_result.json index f4bef67148..4682e9442b 100644 --- a/protocol/examples/messageData/federation_result/federation_result.json +++ b/protocol/examples/messageData/federation_result/federation_result.json @@ -2,6 +2,7 @@ "object": "federation", "action": "result", "status": "success", + "public_key": "UvViTxoKsB3XVP_ctkmOKCJpMWb7fCzrcb1XDmhNe7Q=", "challenge": { "data": "eyJvYmplY3QiOiJmZWRlcmF0aW9uIiwiYWN0aW9uIjoiY2hhbGxlbmdlIiwidmFsdWUiOiJlYmEzZTI0ZWZjZDBiNTNmYTY5OTA4YmFkNWQxY2I2OTlkNzk4MGQ5MzEwOWRhMGIyYmZkNTAzN2MyYzg5ZWUwIiwidGltZXN0YW1wIjoxNzEzMzg1NTY4fQ==", "sender": "zXgzQaa_NpUe-v0Zk_4q8k184ohQ5nTQhBDKgncHzq4=", diff --git a/protocol/query/method/message/data/data.json b/protocol/query/method/message/data/data.json index 0dceaba4d6..382d5eb1d0 100644 --- a/protocol/query/method/message/data/data.json +++ b/protocol/query/method/message/data/data.json @@ -64,6 +64,9 @@ { "$ref": "dataFederationChallenge.json" }, + { + "$ref": "dataFederationResult.json" + }, { "$ref": "dataWitnessMessage.json" }, diff --git a/protocol/query/method/message/data/dataFederationResult.json b/protocol/query/method/message/data/dataFederationResult.json index 4f3d7ff786..9737285993 100644 --- a/protocol/query/method/message/data/dataFederationResult.json +++ b/protocol/query/method/message/data/dataFederationResult.json @@ -15,6 +15,7 @@ }, "status": { "type": "string", + "pattern": "^(success|failure)$", "$comment": "status of the authentication attempt" }, "reason": { @@ -31,6 +32,7 @@ "object", "action", "status", + "reason", "challenge" ] }, @@ -45,6 +47,7 @@ }, "status": { "type": "string", + "pattern": "^(success|failure)$", "$comment": "status of the authentication attempt" }, "public_key": { diff --git a/protocol/test/main.js b/protocol/test/main.js index 3075c2f29b..6a918a1b43 100644 --- a/protocol/test/main.js +++ b/protocol/test/main.js @@ -43,6 +43,7 @@ const message_data_federation_init_schema = require("../query/method/message/dat const message_data_federation_expect_schema = require("../query/method/message/data/dataFederationExpect.json") const message_data_federation_challenge_request_schema = require("../query/method/message/data/dataFederationChallengeRequest.json") const message_data_federation_challenge_schema = require("../query/method/message/data/dataFederationChallenge.json") +const message_data_federation_result_schema = require("../query/method/message/data/dataFederationResult.json") const message_data_chirp_add_schema = require("../query/method/message/data/dataAddChirp.json"); const message_data_chirp_notify_add_schema = require("../query/method/message/data/dataNotifyAddChirp.json"); @@ -112,6 +113,7 @@ ajv.addSchema([ message_data_federation_expect_schema, message_data_federation_challenge_request_schema, message_data_federation_challenge_schema, + message_data_federation_result_schema, message_data_chirp_notify_add_schema, message_data_chirp_add_schema, diff --git a/protocol/test/main.test.js b/protocol/test/main.test.js index 6ef0d13286..1c54d5fd05 100644 --- a/protocol/test/main.test.js +++ b/protocol/test/main.test.js @@ -7,7 +7,7 @@ const ajv = require("./main"); const rootSchema = "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/jsonRPC.json"; const messageDataSchema = - "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/query/method/message/data/data.json"; + require("../query/method/message/data/data.json"); // custom validator to display better error message. expect.extend({ @@ -263,6 +263,9 @@ test("message data: federation", () => { federation_challenge = require("../examples/messageData/federation_challenge/federation_challenge.json"); expect(federation_challenge).toBeValid(messageDataSchema); + federation_result = require("../examples/messageData/federation_result/federation_result.json"); + expect(federation_result).toBeValid(messageDataSchema); + }); test("message data: chirp", () => { From 0929ebdb329ed2c75639139d90b9bfb5da64f0b0 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Tue, 30 Apr 2024 13:48:18 +0200 Subject: [PATCH 05/15] change url --- protocol/test/main.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocol/test/main.test.js b/protocol/test/main.test.js index 1c54d5fd05..728da8d012 100644 --- a/protocol/test/main.test.js +++ b/protocol/test/main.test.js @@ -6,8 +6,9 @@ const ajv = require("./main"); const rootSchema = "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/jsonRPC.json"; + const messageDataSchema = - require("../query/method/message/data/data.json"); + "https://raw.githubusercontent.com/dedis/popstellar/master/protocol/query/method/message/data/data.json"; // custom validator to display better error message. expect.extend({ From b2f066a2d77c1a6aae9729310d05b25024e8bc62 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Tue, 30 Apr 2024 14:01:56 +0200 Subject: [PATCH 06/15] change pattern --- protocol/query/method/message/data/dataFederationResult.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/query/method/message/data/dataFederationResult.json b/protocol/query/method/message/data/dataFederationResult.json index 9737285993..512f1d6f08 100644 --- a/protocol/query/method/message/data/dataFederationResult.json +++ b/protocol/query/method/message/data/dataFederationResult.json @@ -15,7 +15,7 @@ }, "status": { "type": "string", - "pattern": "^(success|failure)$", + "pattern": "^failure$", "$comment": "status of the authentication attempt" }, "reason": { @@ -47,7 +47,7 @@ }, "status": { "type": "string", - "pattern": "^(success|failure)$", + "pattern": "^success$", "$comment": "status of the authentication attempt" }, "public_key": { From defed6b13ff60c2f0b385103f0923cde60b2957d Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Wed, 1 May 2024 16:23:09 +0200 Subject: [PATCH 07/15] adapt federation result schema & test --- be1-go/channel/federation/federation_test.go | 15 ++++++++++++--- be1-go/message/messagedata/federation_result.go | 7 ++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/be1-go/channel/federation/federation_test.go b/be1-go/channel/federation/federation_test.go index 18c0e4f7c4..888b0c550a 100644 --- a/be1-go/channel/federation/federation_test.go +++ b/be1-go/channel/federation/federation_test.go @@ -368,6 +368,7 @@ func Test_FederationResult(t *testing.T) { "federation_challenge", "federation_challenge.json") challengeBytes, err := os.ReadFile(challengeFile) + challengeBase64 := base64.URLEncoding.EncodeToString(challengeBytes) require.NoError(t, err) signedChallengeBytes, err := schnorr.Sign(crypto.Suite, organizerKeypair.private, challengeBytes) require.NoError(t, err) @@ -379,9 +380,17 @@ func Test_FederationResult(t *testing.T) { t.Log() federationResultData := messagedata.FederationResult{ - Object: messagedata.FederationObject, - Action: messagedata.FederationActionResult, - Status: "success", + Object: messagedata.FederationObject, + Action: messagedata.FederationActionResult, + Status: "success", + PublicKey: remoteOrganizerKeypair.publicKey, + ChallengeMsg: message.Message{ + Data: challengeBase64, + Sender: organizerKeypair.publicKey, + Signature: signedChallengeBase64, + MessageID: messagedata.Hash(challengeBase64, signedChallengeBase64), + WitnessSignatures: []message.WitnessSignature{}, + }, } resultMsg := generateMessage(t, organizerKeypair, federationResultData) publishMsg := generatePublish(t, localFedChannel, resultMsg) diff --git a/be1-go/message/messagedata/federation_result.go b/be1-go/message/messagedata/federation_result.go index ac7d39a026..88a5987678 100644 --- a/be1-go/message/messagedata/federation_result.go +++ b/be1-go/message/messagedata/federation_result.go @@ -1,12 +1,17 @@ package messagedata +import "popstellar/message/query/method/message" + // FederationResult defines a message data type FederationResult struct { Object string `json:"object"` Action string `json:"action"` - Status string `json:"status"` + Reason string `json:"reason,omitempty"` + + PublicKey string `json:"public_key,omitempty"` + ChallengeMsg message.Message `json:"challenge"` } // GetObject implements MessageData From bcae615670106360d39877a472257a31c36cbfc7 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Wed, 1 May 2024 17:16:15 +0200 Subject: [PATCH 08/15] add initial result handling (+ rename wrongly named file) --- be1-go/channel/federation/federation.go | 32 +++++++++++++++++++ be1-go/channel/federation/federation_test.go | 7 +--- ...on_expect.json.go => federation_expect.go} | 0 3 files changed, 33 insertions(+), 6 deletions(-) rename be1-go/message/messagedata/{federation_expect.json.go => federation_expect.go} (100%) diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index 163d816a83..2104ec41b3 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -7,9 +7,12 @@ import ( "encoding/json" "fmt" "github.com/rs/zerolog" + "go.dedis.ch/kyber/v3" + "go.dedis.ch/kyber/v3/sign/schnorr" "golang.org/x/xerrors" "popstellar/channel" "popstellar/channel/registry" + "popstellar/crypto" "popstellar/inbox" jsonrpc "popstellar/message" "popstellar/message/answer" @@ -506,5 +509,34 @@ func (c *Channel) processFederationResult(msg message.Message, return xerrors.Errorf("failed to establish federated connection") } + challengeDataBytes, err := base64.URLEncoding.DecodeString(federationResult.ChallengeMsg.Data) + if err != nil { + return xerrors.Errorf("failed to decode challenge data in FederationResult: %v", err) + + } + + challengeSignatureBytes, err := base64.URLEncoding.DecodeString(federationResult.ChallengeMsg.Signature) + if err != nil { + return xerrors.Errorf("failed to decode challenge signature in FederationResult: %v", err) + + } + + pkBytes, err := base64.URLEncoding.DecodeString(c.remoteOrganizerPk) + if err != nil { + return xerrors.Errorf("failed to decode remote organizers public key: %v", err) + + } + var remotePk kyber.Point + err = kyber.Point.UnmarshalBinary(remotePk, pkBytes) + if err != nil { + return xerrors.Errorf("failed to decode remote organizers public key: %v", err) + + } + err = schnorr.Verify(crypto.Suite, remotePk, challengeDataBytes, challengeSignatureBytes) + if err != nil { + return xerrors.Errorf("failed to verify signature on challenge in FederationResult message: %v", err) + + } + return nil } diff --git a/be1-go/channel/federation/federation_test.go b/be1-go/channel/federation/federation_test.go index 888b0c550a..9db5587465 100644 --- a/be1-go/channel/federation/federation_test.go +++ b/be1-go/channel/federation/federation_test.go @@ -374,16 +374,11 @@ func Test_FederationResult(t *testing.T) { require.NoError(t, err) signedChallengeBase64 := base64.URLEncoding.EncodeToString(signedChallengeBytes) - t.Log(signedRemotePublicKeyBase64) - t.Log(signedChallengeBase64) - t.Log() - t.Log() - federationResultData := messagedata.FederationResult{ Object: messagedata.FederationObject, Action: messagedata.FederationActionResult, Status: "success", - PublicKey: remoteOrganizerKeypair.publicKey, + PublicKey: signedRemotePublicKeyBase64, ChallengeMsg: message.Message{ Data: challengeBase64, Sender: organizerKeypair.publicKey, diff --git a/be1-go/message/messagedata/federation_expect.json.go b/be1-go/message/messagedata/federation_expect.go similarity index 100% rename from be1-go/message/messagedata/federation_expect.json.go rename to be1-go/message/messagedata/federation_expect.go From beff40f00803a09d3c10507d0252a28b5ede2833 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Sun, 5 May 2024 15:11:38 +0200 Subject: [PATCH 09/15] finalized result handling & changed tests --- be1-go/channel/federation/federation.go | 29 +++++++++++-- be1-go/channel/federation/federation_test.go | 43 +++++++++++++------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index 2104ec41b3..983b7741cb 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "github.com/rs/zerolog" - "go.dedis.ch/kyber/v3" "go.dedis.ch/kyber/v3/sign/schnorr" "golang.org/x/xerrors" "popstellar/channel" @@ -205,6 +204,9 @@ func (c *Channel) processFederationInit(msg message.Message, return xerrors.Errorf("failed to unmarshal FederationInit data: %v", err) } + // set remote organizer public key + c.remoteOrganizerPk = federationInit.PublicKey + c.remoteServer, err = c.hub.ConnectToServerAsClient(federationInit.ServerAddress) if err != nil { c.state = None @@ -526,8 +528,10 @@ func (c *Channel) processFederationResult(msg message.Message, return xerrors.Errorf("failed to decode remote organizers public key: %v", err) } - var remotePk kyber.Point - err = kyber.Point.UnmarshalBinary(remotePk, pkBytes) + + remotePk := crypto.Suite.Point() + + err = remotePk.UnmarshalBinary(pkBytes) if err != nil { return xerrors.Errorf("failed to decode remote organizers public key: %v", err) @@ -538,5 +542,24 @@ func (c *Channel) processFederationResult(msg message.Message, } + pkSignatureBytes, err := base64.URLEncoding.DecodeString(federationResult.PublicKey) + if err != nil { + return xerrors.Errorf("failed to decode signature on local public key in FederationResult message: %v", err) + + } + localPkBinary, err := c.hub.GetPubKeyOwner().MarshalBinary() + if err != nil { + return xerrors.Errorf("failed to marshal local organizer public key: %v", err) + + } + + err = schnorr.Verify(crypto.Suite, remotePk, localPkBinary, pkSignatureBytes) + if err != nil { + return xerrors.Errorf("failed to verify remote signature on local organizer public key: %v", err) + + } + + c.state = Connected + return nil } diff --git a/be1-go/channel/federation/federation_test.go b/be1-go/channel/federation/federation_test.go index 9db5587465..131c0d8c2e 100644 --- a/be1-go/channel/federation/federation_test.go +++ b/be1-go/channel/federation/federation_test.go @@ -5,17 +5,12 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - "go.dedis.ch/kyber/v3" - "go.dedis.ch/kyber/v3/sign/schnorr" - "golang.org/x/sync/semaphore" - "golang.org/x/xerrors" "io" "os" "path/filepath" "popstellar/channel" "popstellar/crypto" + "popstellar/inbox" jsonrpc "popstellar/message" "popstellar/message/messagedata" "popstellar/message/query" @@ -26,6 +21,13 @@ import ( "sync" "testing" "time" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" + "go.dedis.ch/kyber/v3" + "go.dedis.ch/kyber/v3/sign/schnorr" + "golang.org/x/sync/semaphore" + "golang.org/x/xerrors" ) const ( @@ -354,15 +356,28 @@ func Test_FederationResult(t *testing.T) { fakeHub, err := NewFakeHub("", organizerKeypair.public, nolog, nil) require.NoError(t, err) - fedChannel := NewChannel(localFedChannel, fakeHub, nolog, - organizerKeypair.publicKey) + // dirty hack to manually create a channel, so we can then add the remote organizer pk without + // having to go through the init process + + box := inbox.NewInbox(localFedChannel) + newChannel := &Channel{ + sockets: channel.NewSockets(), + inbox: box, + channelID: localFedChannel, + hub: fakeHub, + log: nolog, + localOrganizerPk: organizerKeypair.publicKey, + remoteOrganizerPk: remoteOrganizerKeypair.publicKey, + state: None, + } + newChannel.registry = newChannel.NewFederationRegistry() - remotePublicKeyBytes, err := remoteOrganizerKeypair.public.MarshalBinary() + publicKeyBytes, err := organizerKeypair.public.MarshalBinary() require.NoError(t, err) - signedRemotePublicKey, err := schnorr.Sign(crypto.Suite, organizerKeypair.private, remotePublicKeyBytes) + signedPublicKey, err := schnorr.Sign(crypto.Suite, remoteOrganizerKeypair.private, publicKeyBytes) require.NoError(t, err) - signedRemotePublicKeyBase64 := base64.URLEncoding.EncodeToString(signedRemotePublicKey) + signedPublicKeyBase64 := base64.URLEncoding.EncodeToString(signedPublicKey) challengeFile := filepath.Join(relativeMsgDataExamplePath, "federation_challenge", @@ -370,7 +385,7 @@ func Test_FederationResult(t *testing.T) { challengeBytes, err := os.ReadFile(challengeFile) challengeBase64 := base64.URLEncoding.EncodeToString(challengeBytes) require.NoError(t, err) - signedChallengeBytes, err := schnorr.Sign(crypto.Suite, organizerKeypair.private, challengeBytes) + signedChallengeBytes, err := schnorr.Sign(crypto.Suite, remoteOrganizerKeypair.private, challengeBytes) require.NoError(t, err) signedChallengeBase64 := base64.URLEncoding.EncodeToString(signedChallengeBytes) @@ -378,7 +393,7 @@ func Test_FederationResult(t *testing.T) { Object: messagedata.FederationObject, Action: messagedata.FederationActionResult, Status: "success", - PublicKey: signedRemotePublicKeyBase64, + PublicKey: signedPublicKeyBase64, ChallengeMsg: message.Message{ Data: challengeBase64, Sender: organizerKeypair.publicKey, @@ -391,7 +406,7 @@ func Test_FederationResult(t *testing.T) { publishMsg := generatePublish(t, localFedChannel, resultMsg) socket := &fakeSocket{id: "sockSocket"} - err = fedChannel.Publish(publishMsg, socket) + err = newChannel.Publish(publishMsg, socket) require.NoError(t, err) } From dceb6786ac22e8113464822930c3fe26b3cc52a0 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Tue, 7 May 2024 15:21:55 +0200 Subject: [PATCH 10/15] change remoteOrganisations map back to using remote organizers pk --- be1-go/channel/federation/federation.go | 71 ++++++++++--------- be1-go/channel/federation/federation_test.go | 23 +++--- .../messagedata/federation_challenge.go | 13 ++-- .../message/messagedata/federation_expect.go | 10 +-- .../federation_expect/federation_expect.json | 12 +++- .../message/data/dataFederationExpect.json | 11 ++- 6 files changed, 80 insertions(+), 60 deletions(-) diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index f9bbda3d1e..89f6df7c61 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -42,15 +42,17 @@ const ( ) type remoteOrganization struct { - laoId string - fedChannel string - organizerPk string + laoId string + fedChannel string + organizerPk string + signedOrganizerPk string // store the pop tokens of the other lao // popTokens map[string]struct{} - challenge messagedata.Challenge - socket socket.Socket + challenge messagedata.FederationChallenge + challengeMsg message.Message + socket socket.Socket state State sync.Mutex @@ -67,11 +69,11 @@ type Channel struct { localOrganizerPk string - // map challenge -> remoteOrganization + // map remoteOrganizerPk -> remoteOrganization remoteOrganizations map[string]*remoteOrganization // list of challenge requested but not used yet - challenges map[messagedata.Challenge]struct{} + challenges map[messagedata.FederationChallenge]struct{} sync.Mutex } @@ -90,7 +92,7 @@ func NewChannel(channelID string, hub channel.HubFunctionalities, log: log, localOrganizerPk: organizerPk, remoteOrganizations: make(map[string]*remoteOrganization), - challenges: make(map[messagedata.Challenge]struct{}), + challenges: make(map[messagedata.FederationChallenge]struct{}), } newChannel.registry = newChannel.NewFederationRegistry() @@ -221,7 +223,7 @@ func (c *Channel) processFederationInit(msg message.Message, return xerrors.Errorf("failed to unmarshal FederationChallenge data: %v", err) } - remoteOrg := c.getRemoteOrganization(federationChallenge.Value) + remoteOrg := c.getRemoteOrganization(federationInit.PublicKey) remoteOrg.Lock() defer remoteOrg.Unlock() @@ -233,10 +235,7 @@ func (c *Channel) processFederationInit(msg message.Message, remoteOrg.organizerPk = federationInit.PublicKey remoteOrg.laoId = federationInit.LaoId remoteOrg.fedChannel = fmt.Sprintf("/root/%s/federation", federationInit.LaoId) - remoteOrg.challenge = messagedata.Challenge{ - Value: federationChallenge.Value, - ValidUntil: federationChallenge.Timestamp, - } + remoteOrg.challenge = federationChallenge remoteOrg.socket, err = c.hub.ConnectToServerAsClient(federationInit.ServerAddress) if err != nil { @@ -297,30 +296,36 @@ func (c *Channel) processFederationExpect(msg message.Message, return xerrors.Errorf("failed to unmarshal federationExpect data: %v", err) } - remoteOrg := c.getRemoteOrganization(federationExpect.Challenge.Value) + remoteOrg := c.getRemoteOrganization(federationExpect.PublicKey) remoteOrg.Lock() defer remoteOrg.Unlock() if remoteOrg.state != None { return answer.NewInternalServerError(invalidStateError, remoteOrg.state, msg) } + var federationChallenge messagedata.FederationChallenge + err = msg.UnmarshalData(&federationChallenge) + if err != nil { + return xerrors.Errorf("failed to unmarshal federationChallenge data: %v", err) + } c.Lock() - _, ok = c.challenges[federationExpect.Challenge] + _, ok = c.challenges[federationChallenge] // always remove the challenge, if present, to avoid challenge reuse - delete(c.challenges, federationExpect.Challenge) + delete(c.challenges, federationChallenge) c.Unlock() if !ok { return answer.NewAccessDeniedError("Invalid challenge %v", - federationExpect.Challenge) + federationChallenge) } remoteOrg.state = ExpectConnect - remoteOrg.challenge = federationExpect.Challenge + remoteOrg.challenge = federationChallenge remoteOrg.organizerPk = federationExpect.PublicKey remoteOrg.laoId = federationExpect.LaoId remoteOrg.fedChannel = fmt.Sprintf("/root/%s/federation", federationExpect.LaoId) + remoteOrg.challengeMsg = federationExpect.ChallengeMsg return nil } @@ -372,10 +377,13 @@ func (c *Channel) processFederationChallenge(msg message.Message, remoteOrg.state = WaitResult remoteOrg.socket = s + federationResultData := messagedata.FederationResult{ - Object: messagedata.FederationObject, - Action: messagedata.FederationActionResult, - Status: "success", + Object: messagedata.FederationObject, + Action: messagedata.FederationActionResult, + Status: "success", + PublicKey: remoteOrg.signedOrganizerPk, + ChallengeMsg: remoteOrg.challengeMsg, } dataBytes, err := json.Marshal(federationResultData) @@ -453,22 +461,17 @@ func (c *Channel) processChallengeRequest(msg message.Message, } challengeValue := hex.EncodeToString(randomBytes) expirationTime := time.Now().Add(time.Minute * 5).Unix() - challenge := messagedata.Challenge{ + federationChallenge := messagedata.FederationChallenge{ + Object: messagedata.FederationObject, + Action: messagedata.FederationActionChallenge, Value: challengeValue, ValidUntil: expirationTime, } c.Lock() - c.challenges[challenge] = struct{}{} + c.challenges[federationChallenge] = struct{}{} c.Unlock() - federationChallenge := messagedata.FederationChallenge{ - Object: messagedata.FederationObject, - Action: messagedata.FederationActionChallenge, - Value: challengeValue, - Timestamp: expirationTime, - } - challengeData, err := json.Marshal(federationChallenge) if err != nil { return xerrors.Errorf( @@ -614,16 +617,16 @@ func (c *Channel) processFederationResult(msg message.Message, return nil } -// getRemoteOrganization get the remoteOrganization for a given challenge +// getRemoteOrganization get the remoteOrganization for the given organizerPk // or return a new empty one. -func (c *Channel) getRemoteOrganization(challenge string) *remoteOrganization { +func (c *Channel) getRemoteOrganization(organizerPk string) *remoteOrganization { c.Lock() defer c.Unlock() - org, ok := c.remoteOrganizations[challenge] + org, ok := c.remoteOrganizations[organizerPk] if !ok { org = &remoteOrganization{state: None} - c.remoteOrganizations[challenge] = org + c.remoteOrganizations[organizerPk] = org } return org diff --git a/be1-go/channel/federation/federation_test.go b/be1-go/channel/federation/federation_test.go index 69d4c96263..4d6ab5f25a 100644 --- a/be1-go/channel/federation/federation_test.go +++ b/be1-go/channel/federation/federation_test.go @@ -89,7 +89,7 @@ func Test_FederationRequestChallenge(t *testing.T) { require.Equal(t, messagedata.FederationObject, challenge.Object) require.Equal(t, messagedata.FederationActionChallenge, challenge.Action) - require.Greater(t, challenge.Timestamp, time.Now().Unix()) + require.Greater(t, challenge.ValidUntil, time.Now().Unix()) bytes, err := hex.DecodeString(challenge.Value) require.NoError(t, err) require.Len(t, bytes, 32) @@ -163,10 +163,7 @@ func Test_FederationExpect(t *testing.T) { LaoId: remoteLaoId, ServerAddress: remoteServerAddress, PublicKey: remoteOrganizerKeypair.publicKey, - Challenge: messagedata.Challenge{ - Value: challenge.Value, - ValidUntil: challenge.Timestamp, - }, + ChallengeMsg: challengeMsg, } federationMsg := generateMessage(t, organizerKeypair, federationExpect) @@ -214,9 +211,12 @@ func Test_FederationExpect_with_invalid_challenge(t *testing.T) { LaoId: remoteLaoId, ServerAddress: remoteServerAddress, PublicKey: remoteOrganizerKeypair.publicKey, - Challenge: messagedata.Challenge{ - Value: hex.EncodeToString(valueBytes), - ValidUntil: time.Now().Unix(), + ChallengeMsg: message.Message{ + Data: "aaaaaaaaaaa", + Sender: organizerKeypair.publicKey, + Signature: "bbbbbbbbbbb", + MessageID: messagedata.Hash("aaaaaaaaaaa", "bbbbbbbbbbb"), + WitnessSignatures: []message.WitnessSignature{}, }, } @@ -271,10 +271,7 @@ func Test_FederationChallenge_not_organizer(t *testing.T) { LaoId: remoteLaoId, ServerAddress: remoteServerAddress, PublicKey: remoteOrganizerKeypair.publicKey, - Challenge: messagedata.Challenge{ - Value: challenge.Value, - ValidUntil: challenge.Timestamp, - }, + ChallengeMsg: challengeMsg, } federationMsg := generateMessage(t, notOrganizerKeypair, federationExpect) @@ -407,7 +404,7 @@ func Test_FederationResult(t *testing.T) { PublicKey: signedPublicKeyBase64, ChallengeMsg: message.Message{ Data: challengeBase64, - Sender: organizerKeypair.publicKey, + Sender: remoteOrganizerKeypair.publicKey, Signature: signedChallengeBase64, MessageID: messagedata.Hash(challengeBase64, signedChallengeBase64), WitnessSignatures: []message.WitnessSignature{}, diff --git a/be1-go/message/messagedata/federation_challenge.go b/be1-go/message/messagedata/federation_challenge.go index af9909651f..1bf6a36db8 100644 --- a/be1-go/message/messagedata/federation_challenge.go +++ b/be1-go/message/messagedata/federation_challenge.go @@ -6,16 +6,15 @@ type FederationChallenge struct { Action string `json:"action"` // Value is a 32 bytes array encoded in hexadecimal - Value string `json:"value"` - // Timestamp is a Unix timestamp - Timestamp int64 `json:"timestamp"` -} - -type Challenge struct { Value string `json:"value"` - ValidUntil int64 `json:"valid_until"` + ValidUntil int64 `json:"timestamp"` } +//type Challenge struct { +// Value string `json:"value"` +// ValidUntil int64 `json:"valid_until"` +//} + // GetObject implements MessageData func (FederationChallenge) GetObject() string { return FederationObject diff --git a/be1-go/message/messagedata/federation_expect.go b/be1-go/message/messagedata/federation_expect.go index f56bb4023d..7e909c62f3 100644 --- a/be1-go/message/messagedata/federation_expect.go +++ b/be1-go/message/messagedata/federation_expect.go @@ -1,14 +1,16 @@ package messagedata +import "popstellar/message/query/method/message" + // FederationExpect defines a message data type FederationExpect struct { Object string `json:"object"` Action string `json:"action"` - LaoId string `json:"lao_id"` - ServerAddress string `json:"server_address"` - PublicKey string `json:"public_key"` - Challenge Challenge `json:"challenge"` + LaoId string `json:"lao_id"` + ServerAddress string `json:"server_address"` + PublicKey string `json:"public_key"` + ChallengeMsg message.Message `json:"challenge"` } // GetObject implements MessageData diff --git a/protocol/examples/messageData/federation_expect/federation_expect.json b/protocol/examples/messageData/federation_expect/federation_expect.json index 4d09f9a06b..1713c4a24e 100644 --- a/protocol/examples/messageData/federation_expect/federation_expect.json +++ b/protocol/examples/messageData/federation_expect/federation_expect.json @@ -5,7 +5,17 @@ "public_key": "UvViTxoKsB3XVP_ctkmOKCJpMWb7fCzrcb1XDmhNe7Q=", "server_address": "wss://ethz.ch:9000/server", "challenge": { +<<<<<<< Updated upstream "value": "82eadde2a4ba832518b90bb93c8480ee1ae16a91d5efe9281e91e2ec11da03e4", "valid_until": 1712854874 } -} \ No newline at end of file +} +======= + "data": "eyJvYmplY3QiOiJmZWRlcmF0aW9uIiwiYWN0aW9uIjoiY2hhbGxlbmdlIiwidmFsdWUiOiI4MmVhZGRlMmE0YmE4MzI1MThiOTBiYjkzYzg0ODBlZTFhZTE2YTkxZDVlZmU5MjgxZTkxZTJlYzExZGEwM2U0IiwidmFsaWRfdW50aWwiOjE3MTI4NTQ4NzR9", + "sender": "zXgzQaa_NpUe-v0Zk_4q8k184ohQ5nTQhBDKgncHzq4=", + "signature": "BILYwYkT5tOBL4rCD7yvhBkhAYqRXOI3ajQ2uJ1gAk-g6nRc38vMMnlHShuNCQ3dQFXYZPn37cCFelhWGjY8Bg==", + "message_id": "sD_PdryBuOr14_65h8L-e1lzdQpDWxUAngtu1uwqgEI=", + "witness_signatures": [] + } +} +>>>>>>> Stashed changes diff --git a/protocol/query/method/message/data/dataFederationExpect.json b/protocol/query/method/message/data/dataFederationExpect.json index c1ce945a4d..3023be234a 100644 --- a/protocol/query/method/message/data/dataFederationExpect.json +++ b/protocol/query/method/message/data/dataFederationExpect.json @@ -26,6 +26,7 @@ "$comment": "public key of the remote organizer" }, "challenge": { +<<<<<<< Updated upstream "type": "object", "properties": { "value": { @@ -42,6 +43,10 @@ }, "additionalProperties": false, "required": ["value", "valid_until"] +======= + "$ref": "../message.json", + "$comment": "message/message containing a FederationChallenge data" +>>>>>>> Stashed changes } }, "additionalProperties": false, @@ -53,4 +58,8 @@ "public_key", "challenge" ] -} \ No newline at end of file +<<<<<<< Updated upstream +} +======= +} +>>>>>>> Stashed changes From dc3afd89ad1e91d20da0bda2b2f317a27247378c Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Wed, 8 May 2024 16:27:14 +0200 Subject: [PATCH 11/15] change challenge check & remove wrongly added merge remainders --- be1-go/channel/federation/federation.go | 3 +-- be1-go/channel/federation/federation_test.go | 1 + .../message/data/dataFederationExpect.json | 23 ------------------- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index 89f6df7c61..bfb4cf6e5a 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -295,7 +295,6 @@ func (c *Channel) processFederationExpect(msg message.Message, if err != nil { return xerrors.Errorf("failed to unmarshal federationExpect data: %v", err) } - remoteOrg := c.getRemoteOrganization(federationExpect.PublicKey) remoteOrg.Lock() defer remoteOrg.Unlock() @@ -304,7 +303,7 @@ func (c *Channel) processFederationExpect(msg message.Message, return answer.NewInternalServerError(invalidStateError, remoteOrg.state, msg) } var federationChallenge messagedata.FederationChallenge - err = msg.UnmarshalData(&federationChallenge) + err = federationExpect.ChallengeMsg.UnmarshalData(&federationChallenge) if err != nil { return xerrors.Errorf("failed to unmarshal federationChallenge data: %v", err) } diff --git a/be1-go/channel/federation/federation_test.go b/be1-go/channel/federation/federation_test.go index 4d6ab5f25a..0807cd1c91 100644 --- a/be1-go/channel/federation/federation_test.go +++ b/be1-go/channel/federation/federation_test.go @@ -154,6 +154,7 @@ func Test_FederationExpect(t *testing.T) { var challenge messagedata.FederationChallenge err = challengeMsg.UnmarshalData(&challenge) require.NoError(t, err) + t.Log(challengeMsg) remoteOrganizerKeypair := generateKeyPair(t) diff --git a/protocol/query/method/message/data/dataFederationExpect.json b/protocol/query/method/message/data/dataFederationExpect.json index 3023be234a..9bd86f2bac 100644 --- a/protocol/query/method/message/data/dataFederationExpect.json +++ b/protocol/query/method/message/data/dataFederationExpect.json @@ -26,27 +26,8 @@ "$comment": "public key of the remote organizer" }, "challenge": { -<<<<<<< Updated upstream - "type": "object", - "properties": { - "value": { - "type": "string", - "contentEncoding": "hex", - "pattern": "^[0-9a-fA-F]{64}$", - "$comment": "A 32 bytes array encoded in hexadecimal" - }, - "valid_until": { - "type": "integer", - "description": "[Timestamp] of the expiration time", - "minimum": 0 - } - }, - "additionalProperties": false, - "required": ["value", "valid_until"] -======= "$ref": "../message.json", "$comment": "message/message containing a FederationChallenge data" ->>>>>>> Stashed changes } }, "additionalProperties": false, @@ -58,8 +39,4 @@ "public_key", "challenge" ] -<<<<<<< Updated upstream } -======= -} ->>>>>>> Stashed changes From 6a837ae1e0d490394f19bb3056377d636563eb88 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Wed, 8 May 2024 16:42:15 +0200 Subject: [PATCH 12/15] remove more merge remainders --- .../messageData/federation_expect/federation_expect.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/protocol/examples/messageData/federation_expect/federation_expect.json b/protocol/examples/messageData/federation_expect/federation_expect.json index 1713c4a24e..159c608a2d 100644 --- a/protocol/examples/messageData/federation_expect/federation_expect.json +++ b/protocol/examples/messageData/federation_expect/federation_expect.json @@ -5,12 +5,6 @@ "public_key": "UvViTxoKsB3XVP_ctkmOKCJpMWb7fCzrcb1XDmhNe7Q=", "server_address": "wss://ethz.ch:9000/server", "challenge": { -<<<<<<< Updated upstream - "value": "82eadde2a4ba832518b90bb93c8480ee1ae16a91d5efe9281e91e2ec11da03e4", - "valid_until": 1712854874 - } -} -======= "data": "eyJvYmplY3QiOiJmZWRlcmF0aW9uIiwiYWN0aW9uIjoiY2hhbGxlbmdlIiwidmFsdWUiOiI4MmVhZGRlMmE0YmE4MzI1MThiOTBiYjkzYzg0ODBlZTFhZTE2YTkxZDVlZmU5MjgxZTkxZTJlYzExZGEwM2U0IiwidmFsaWRfdW50aWwiOjE3MTI4NTQ4NzR9", "sender": "zXgzQaa_NpUe-v0Zk_4q8k184ohQ5nTQhBDKgncHzq4=", "signature": "BILYwYkT5tOBL4rCD7yvhBkhAYqRXOI3ajQ2uJ1gAk-g6nRc38vMMnlHShuNCQ3dQFXYZPn37cCFelhWGjY8Bg==", @@ -18,4 +12,3 @@ "witness_signatures": [] } } ->>>>>>> Stashed changes From 20d4fc419b81e77c0e26276e2d2ebbdccb7929c8 Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Sun, 12 May 2024 19:16:32 +0200 Subject: [PATCH 13/15] added suggestions --- be1-go/channel/federation/federation.go | 60 ++++++++++++-------- be1-go/channel/federation/federation_test.go | 10 ++-- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index bfb4cf6e5a..f11baa9709 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -1,14 +1,12 @@ package federation import ( + "bytes" "crypto/rand" "encoding/base64" "encoding/hex" "encoding/json" "fmt" - "github.com/rs/zerolog" - "go.dedis.ch/kyber/v3/sign/schnorr" - "golang.org/x/xerrors" "popstellar/channel" "popstellar/channel/registry" "popstellar/crypto" @@ -24,6 +22,10 @@ import ( "strconv" "sync" "time" + + "github.com/rs/zerolog" + "go.dedis.ch/kyber/v3/sign/schnorr" + "golang.org/x/xerrors" ) const ( @@ -42,10 +44,9 @@ const ( ) type remoteOrganization struct { - laoId string - fedChannel string - organizerPk string - signedOrganizerPk string + laoId string + fedChannel string + organizerPk string // store the pop tokens of the other lao // popTokens map[string]struct{} @@ -270,6 +271,7 @@ func (c *Channel) processFederationInit(msg message.Message, } remoteOrg.socket.Send(buf) + remoteOrg.state = WaitResult return nil } @@ -381,7 +383,7 @@ func (c *Channel) processFederationChallenge(msg message.Message, Object: messagedata.FederationObject, Action: messagedata.FederationActionResult, Status: "success", - PublicKey: remoteOrg.signedOrganizerPk, + PublicKey: remoteOrg.organizerPk, ChallengeMsg: remoteOrg.challengeMsg, } @@ -397,9 +399,15 @@ func (c *Channel) processFederationChallenge(msg message.Message, } signatureBase64 := base64.URLEncoding.EncodeToString(signatureBytes) + serverPubKey, err := c.hub.GetPubKeyServ().MarshalBinary() + if err != nil { + return xerrors.Errorf("failed to marshal public key of server: %v", err) + + } + federationResultMsg := message.Message{ Data: dataBase64, - Sender: c.hub.GetPubKeyServ().String(), + Sender: base64.URLEncoding.EncodeToString(serverPubKey), Signature: signatureBase64, MessageID: messagedata.Hash(dataBase64, signatureBase64), WitnessSignatures: []message.WitnessSignature{}, @@ -427,6 +435,7 @@ func (c *Channel) processFederationChallenge(msg message.Message, } remoteOrg.socket.Send(buf) + return nil } @@ -533,13 +542,6 @@ func (c *Channel) processFederationResult(msg message.Message, msgData) } - /* - This state should probably be set after sending the FederationInit message? - */ - //if c.state != WaitResult { - // return answer.NewInternalServerError(invalidStateError, c.state, msg) - //} - var federationResult messagedata.FederationResult err := msg.UnmarshalData(&federationResult) @@ -572,9 +574,15 @@ func (c *Channel) processFederationResult(msg message.Message, } - remoteOrg := c.getRemoteOrganization(federationChallenge.Value) + remoteOrg := c.getRemoteOrganization(federationResult.ChallengeMsg.Sender) remoteOrg.Lock() defer remoteOrg.Unlock() + + if remoteOrg.state != WaitResult { + return answer.NewInternalServerError(invalidStateError, remoteOrg.state, msg) + + } + pkBytes, err := base64.URLEncoding.DecodeString(remoteOrg.organizerPk) if err != nil { return xerrors.Errorf("failed to decode remote organizers public key: %v", err) @@ -594,23 +602,27 @@ func (c *Channel) processFederationResult(msg message.Message, } - pkSignatureBytes, err := base64.URLEncoding.DecodeString(federationResult.PublicKey) + resultPkBytes, err := base64.URLEncoding.DecodeString(federationResult.PublicKey) if err != nil { - return xerrors.Errorf("failed to decode signature on local public key in FederationResult message: %v", err) + return xerrors.Errorf("failed to decode local public key in FederationResult message: %v", err) } - localPkBinary, err := c.hub.GetPubKeyOwner().MarshalBinary() + localPkBytes, err := c.hub.GetPubKeyOwner().MarshalBinary() if err != nil { return xerrors.Errorf("failed to marshal local organizer public key: %v", err) } - - err = schnorr.Verify(crypto.Suite, remotePk, localPkBinary, pkSignatureBytes) - if err != nil { - return xerrors.Errorf("failed to verify remote signature on local organizer public key: %v", err) + if !(bytes.Equal(resultPkBytes, localPkBytes)) { + return xerrors.Errorf("invalid public key contained in FederationResult message") } + //err = schnorr.Verify(crypto.Suite, remotePk, localPkBinary, pkSignatureBytes) + //if err != nil { + // return xerrors.Errorf("failed to verify remote signature on local organizer public key: %v", err) + + //} + remoteOrg.state = Connected return nil diff --git a/be1-go/channel/federation/federation_test.go b/be1-go/channel/federation/federation_test.go index 0807cd1c91..884cb02340 100644 --- a/be1-go/channel/federation/federation_test.go +++ b/be1-go/channel/federation/federation_test.go @@ -154,7 +154,6 @@ func Test_FederationExpect(t *testing.T) { var challenge messagedata.FederationChallenge err = challengeMsg.UnmarshalData(&challenge) require.NoError(t, err) - t.Log(challengeMsg) remoteOrganizerKeypair := generateKeyPair(t) @@ -364,9 +363,10 @@ func Test_FederationResult(t *testing.T) { state: None, } remoteOrg.organizerPk = remoteOrganizerKeypair.publicKey + remoteOrg.state = WaitResult var remoteOrgs = map[string]*remoteOrganization{ - "82eadde2a4ba832518b90bb93c8480ee1ae16a91d5efe9281e91e2ec11da03e4": remoteOrg, + remoteOrganizerKeypair.publicKey: remoteOrg, } newChannel := &Channel{ @@ -383,7 +383,7 @@ func Test_FederationResult(t *testing.T) { publicKeyBytes, err := organizerKeypair.public.MarshalBinary() require.NoError(t, err) - signedPublicKey, err := schnorr.Sign(crypto.Suite, remoteOrganizerKeypair.private, publicKeyBytes) + //signedPublicKey, err := schnorr.Sign(crypto.Suite, remoteOrganizerKeypair.private, publicKeyBytes) require.NoError(t, err) challengeFile := filepath.Join(relativeMsgDataExamplePath, @@ -393,7 +393,7 @@ func Test_FederationResult(t *testing.T) { challengeBase64 := base64.URLEncoding.EncodeToString(challengeBytes) require.NoError(t, err) - signedPublicKeyBase64 := base64.URLEncoding.EncodeToString(signedPublicKey) + //signedPublicKeyBase64 := base64.URLEncoding.EncodeToString(signedPublicKey) signedChallengeBytes, err := schnorr.Sign(crypto.Suite, remoteOrganizerKeypair.private, challengeBytes) require.NoError(t, err) signedChallengeBase64 := base64.URLEncoding.EncodeToString(signedChallengeBytes) @@ -402,7 +402,7 @@ func Test_FederationResult(t *testing.T) { Object: messagedata.FederationObject, Action: messagedata.FederationActionResult, Status: "success", - PublicKey: signedPublicKeyBase64, + PublicKey: base64.URLEncoding.EncodeToString(publicKeyBytes), ChallengeMsg: message.Message{ Data: challengeBase64, Sender: remoteOrganizerKeypair.publicKey, From 51b0b6df833e3647379628c70683f758c5ffc1a8 Mon Sep 17 00:00:00 2001 From: Florentin A Date: Mon, 13 May 2024 11:59:38 +0200 Subject: [PATCH 14/15] Update be1-go/channel/federation/federation.go Co-authored-by: Arnaud S5 --- be1-go/channel/federation/federation.go | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index f11baa9709..68c1588c4d 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -602,27 +602,10 @@ func (c *Channel) processFederationResult(msg message.Message, } - resultPkBytes, err := base64.URLEncoding.DecodeString(federationResult.PublicKey) - if err != nil { - return xerrors.Errorf("failed to decode local public key in FederationResult message: %v", err) - - } - localPkBytes, err := c.hub.GetPubKeyOwner().MarshalBinary() - if err != nil { - return xerrors.Errorf("failed to marshal local organizer public key: %v", err) - - } - if !(bytes.Equal(resultPkBytes, localPkBytes)) { + if c.localOrganizerPk != federationResult.PublicKey { return xerrors.Errorf("invalid public key contained in FederationResult message") - } - //err = schnorr.Verify(crypto.Suite, remotePk, localPkBinary, pkSignatureBytes) - //if err != nil { - // return xerrors.Errorf("failed to verify remote signature on local organizer public key: %v", err) - - //} - remoteOrg.state = Connected return nil From da1cdb99f586f7331c07d4fb7ef92df45a6b8b7e Mon Sep 17 00:00:00 2001 From: Florentin Aigner Date: Mon, 13 May 2024 12:06:30 +0200 Subject: [PATCH 15/15] fix failing test --- be1-go/channel/federation/federation.go | 1 - 1 file changed, 1 deletion(-) diff --git a/be1-go/channel/federation/federation.go b/be1-go/channel/federation/federation.go index 68c1588c4d..be0de6be22 100644 --- a/be1-go/channel/federation/federation.go +++ b/be1-go/channel/federation/federation.go @@ -1,7 +1,6 @@ package federation import ( - "bytes" "crypto/rand" "encoding/base64" "encoding/hex"