feat: add encryption of the payload exchanged via signal

This commit is contained in:
braginini 2021-05-01 18:29:59 +02:00
parent 4f3799ac65
commit 6cd44f1522
7 changed files with 321 additions and 137 deletions

View File

@ -6,6 +6,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/wiretrustee/wiretrustee/connection" "github.com/wiretrustee/wiretrustee/connection"
sig "github.com/wiretrustee/wiretrustee/signal" sig "github.com/wiretrustee/wiretrustee/signal"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"os" "os"
) )
@ -18,8 +19,14 @@ var (
config, _ := Read(configPath) config, _ := Read(configPath)
myKey, err := wgtypes.ParseKey(config.PrivateKey)
if err != nil {
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
os.Exit(ExitSetupFailed)
}
ctx := context.Background() ctx := context.Background()
signalClient, err := sig.NewClient(config.SignalAddr, ctx) signalClient, err := sig.NewClient(config.SignalAddr, myKey, ctx)
if err != nil { if err != nil {
log.Errorf("error while connecting to the Signal Exchange Service %s: %s", config.SignalAddr, err) log.Errorf("error while connecting to the Signal Exchange Service %s: %s", config.SignalAddr, err)
os.Exit(ExitSetupFailed) os.Exit(ExitSetupFailed)
@ -29,7 +36,7 @@ var (
engine := connection.NewEngine(signalClient, config.StunTurnURLs, config.WgIface, config.WgAddr) engine := connection.NewEngine(signalClient, config.StunTurnURLs, config.WgIface, config.WgAddr)
err = engine.Start(config.PrivateKey, config.Peers) err = engine.Start(myKey, config.Peers)
//signalClient.WaitConnected() //signalClient.WaitConnected()

View File

@ -40,17 +40,9 @@ func NewEngine(signal *signal.Client, stunsTurns []*ice.URL, wgIface string, wgA
} }
} }
func (e *Engine) Start(privateKey string, peers []Peer) error { func (e *Engine) Start(myKey wgtypes.Key, peers []Peer) error {
// setup wireguard err := iface.Create(e.wgIface, e.wgIp)
myKey, err := wgtypes.ParseKey(privateKey)
myPubKey := myKey.PublicKey().String()
if err != nil {
log.Errorf("error parsing Wireguard key %s: [%s]", privateKey, err.Error())
return err
}
err = iface.Create(e.wgIface, e.wgIp)
if err != nil { if err != nil {
log.Errorf("error while creating interface %s: [%s]", e.wgIface, err.Error()) log.Errorf("error while creating interface %s: [%s]", e.wgIface, err.Error())
return err return err
@ -68,7 +60,7 @@ func (e *Engine) Start(privateKey string, peers []Peer) error {
return err return err
} }
e.receiveSignal(myPubKey) e.receiveSignal(myKey.PublicKey().String())
// initialize peer agents // initialize peer agents
for _, peer := range peers { for _, peer := range peers {
@ -141,10 +133,12 @@ func (e *Engine) openPeerConnection(wgPort int, myKey wgtypes.Key, peer Peer) (*
func signalCandidate(candidate ice.Candidate, myKey wgtypes.Key, remoteKey wgtypes.Key, s *signal.Client) error { func signalCandidate(candidate ice.Candidate, myKey wgtypes.Key, remoteKey wgtypes.Key, s *signal.Client) error {
err := s.Send(&sProto.Message{ err := s.Send(&sProto.Message{
Type: sProto.Message_CANDIDATE,
Key: myKey.PublicKey().String(), Key: myKey.PublicKey().String(),
RemoteKey: remoteKey.String(), RemoteKey: remoteKey.String(),
Body: candidate.Marshal(), Body: &sProto.Body{
Type: sProto.Body_CANDIDATE,
Payload: candidate.Marshal(),
},
}) })
if err != nil { if err != nil {
log.Errorf("failed signaling candidate to the remote peer %s %s", remoteKey.String(), err) log.Errorf("failed signaling candidate to the remote peer %s %s", remoteKey.String(), err)
@ -157,18 +151,18 @@ func signalCandidate(candidate ice.Candidate, myKey wgtypes.Key, remoteKey wgtyp
func signalAuth(uFrag string, pwd string, myKey wgtypes.Key, remoteKey wgtypes.Key, s *signal.Client, isAnswer bool) error { func signalAuth(uFrag string, pwd string, myKey wgtypes.Key, remoteKey wgtypes.Key, s *signal.Client, isAnswer bool) error {
var t sProto.Message_Type var t sProto.Body_Type
if isAnswer { if isAnswer {
t = sProto.Message_ANSWER t = sProto.Body_ANSWER
} else { } else {
t = sProto.Message_OFFER t = sProto.Body_OFFER
} }
msg := signal.MarshalCredential(myKey.PublicKey().String(), remoteKey.String(), &signal.Credential{ msg, err := signal.MarshalCredential(myKey, remoteKey, &signal.Credential{
UFrag: uFrag, UFrag: uFrag,
Pwd: pwd}, t) Pwd: pwd}, t)
err := s.Send(msg) err = s.Send(msg)
if err != nil { if err != nil {
return err return err
} }
@ -189,8 +183,8 @@ func (e *Engine) receiveSignal(localKey string) {
return fmt.Errorf("unknown peer %s", msg.Key) return fmt.Errorf("unknown peer %s", msg.Key)
} }
switch msg.Type { switch msg.GetBody().Type {
case sProto.Message_OFFER: case sProto.Body_OFFER:
remoteCred, err := signal.UnMarshalCredential(msg) remoteCred, err := signal.UnMarshalCredential(msg)
if err != nil { if err != nil {
return err return err
@ -205,7 +199,7 @@ func (e *Engine) receiveSignal(localKey string) {
} }
return nil return nil
case sProto.Message_ANSWER: case sProto.Body_ANSWER:
remoteCred, err := signal.UnMarshalCredential(msg) remoteCred, err := signal.UnMarshalCredential(msg)
if err != nil { if err != nil {
return err return err
@ -219,9 +213,9 @@ func (e *Engine) receiveSignal(localKey string) {
return err return err
} }
case sProto.Message_CANDIDATE: case sProto.Body_CANDIDATE:
candidate, err := ice.UnmarshalCandidate(msg.Body) candidate, err := ice.UnmarshalCandidate(msg.GetBody().Payload)
if err != nil { if err != nil {
log.Errorf("failed on parsing remote candidate %s -> %s", candidate, err) log.Errorf("failed on parsing remote candidate %s -> %s", candidate, err)
return err return err

View File

@ -4,8 +4,10 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/cenkalti/backoff/v4" "github.com/cenkalti/backoff/v4"
pb "github.com/golang/protobuf/proto"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/wiretrustee/wiretrustee/signal/proto" "github.com/wiretrustee/wiretrustee/signal/proto"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
@ -21,6 +23,7 @@ import (
// Wraps the Signal Exchange Service gRpc client // Wraps the Signal Exchange Service gRpc client
type Client struct { type Client struct {
key wgtypes.Key
realClient proto.SignalExchangeClient realClient proto.SignalExchangeClient
signalConn *grpc.ClientConn signalConn *grpc.ClientConn
ctx context.Context ctx context.Context
@ -30,11 +33,11 @@ type Client struct {
} }
// Closes underlying connections to the Signal Exchange // Closes underlying connections to the Signal Exchange
func (client *Client) Close() error { func (c *Client) Close() error {
return client.signalConn.Close() return c.signalConn.Close()
} }
func NewClient(addr string, ctx context.Context) (*Client, error) { func NewClient(addr string, key wgtypes.Key, ctx context.Context) (*Client, error) {
conn, err := grpc.DialContext( conn, err := grpc.DialContext(
ctx, ctx,
@ -55,6 +58,7 @@ func NewClient(addr string, ctx context.Context) (*Client, error) {
realClient: proto.NewSignalExchangeClient(conn), realClient: proto.NewSignalExchangeClient(conn),
ctx: ctx, ctx: ctx,
signalConn: conn, signalConn: conn,
key: key,
}, nil }, nil
} }
@ -62,8 +66,8 @@ func NewClient(addr string, ctx context.Context) (*Client, error) {
// The messages will be handled by msgHandler function provided. // The messages will be handled by msgHandler function provided.
// This function runs a goroutine underneath and reconnects to the Signal Exchange if errors occur (e.g. Exchange restart) // This function runs a goroutine underneath and reconnects to the Signal Exchange if errors occur (e.g. Exchange restart)
// The key is the identifier of our Peer (could be Wireguard public key) // The key is the identifier of our Peer (could be Wireguard public key)
func (client *Client) Receive(key string, msgHandler func(msg *proto.Message) error) { func (c *Client) Receive(key string, msgHandler func(msg *proto.Message) error) {
client.connWg.Add(1) c.connWg.Add(1)
go func() { go func() {
var backOff = &backoff.ExponentialBackOff{ var backOff = &backoff.ExponentialBackOff{
@ -77,10 +81,10 @@ func (client *Client) Receive(key string, msgHandler func(msg *proto.Message) er
} }
operation := func() error { operation := func() error {
err := client.connect(key, msgHandler) err := c.connect(key, msgHandler)
if err != nil { if err != nil {
log.Warnf("disconnected from the Signal Exchange due to an error %s. Retrying ... ", err) log.Warnf("disconnected from the Signal Exchange due to an error %s. Retrying ... ", err)
client.connWg.Add(1) c.connWg.Add(1)
return err return err
} }
@ -96,44 +100,44 @@ func (client *Client) Receive(key string, msgHandler func(msg *proto.Message) er
}() }()
} }
func (client *Client) connect(key string, msgHandler func(msg *proto.Message) error) error { func (c *Client) connect(key string, msgHandler func(msg *proto.Message) error) error {
client.stream = nil c.stream = nil
// add key fingerprint to the request header to be identified on the server side // add key fingerprint to the request header to be identified on the server side
md := metadata.New(map[string]string{proto.HeaderId: key}) md := metadata.New(map[string]string{proto.HeaderId: key})
ctx := metadata.NewOutgoingContext(client.ctx, md) ctx := metadata.NewOutgoingContext(c.ctx, md)
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
defer cancel() defer cancel()
stream, err := client.realClient.ConnectStream(ctx) stream, err := c.realClient.ConnectStream(ctx)
client.stream = stream c.stream = stream
if err != nil { if err != nil {
return err return err
} }
//connection established we are good to use the stream //connection established we are good to use the stream
client.connWg.Done() c.connWg.Done()
log.Infof("connected to the Signal Exchange Stream") log.Infof("connected to the Signal Exchange Stream")
return client.receive(stream, msgHandler) return c.receive(stream, msgHandler)
} }
// Waits until the client is connected to the message stream // Waits until the client is connected to the message stream
func (client *Client) WaitConnected() { func (c *Client) WaitConnected() {
client.connWg.Wait() c.connWg.Wait()
} }
// Sends a message to the remote Peer through the Signal Exchange using established stream connection to the Signal Server // Sends a message to the remote Peer through the Signal Exchange using established stream connection to the Signal Server
// The Client.Receive method must be called before sending messages to establish initial connection to the Signal Exchange // The Client.Receive method must be called before sending messages to establish initial connection to the Signal Exchange
// Client.connWg can be used to wait // Client.connWg can be used to wait
func (client *Client) SendToStream(msg *proto.Message) error { func (c *Client) SendToStream(msg *proto.EncryptedMessage) error {
if client.stream == nil { if c.stream == nil {
return fmt.Errorf("connection to the Signal Exchnage has not been established yet. Please call Client.Receive before sending messages") return fmt.Errorf("connection to the Signal Exchnage has not been established yet. Please call Client.Receive before sending messages")
} }
err := client.stream.Send(msg) err := c.stream.Send(msg)
if err != nil { if err != nil {
log.Errorf("error while sending message to peer [%s] [error: %v]", msg.RemoteKey, err) log.Errorf("error while sending message to peer [%s] [error: %v]", msg.RemoteKey, err)
return err return err
@ -142,10 +146,57 @@ func (client *Client) SendToStream(msg *proto.Message) error {
return nil return nil
} }
// Sends a message to the remote Peer through the Signal Exchange. // decryptMessage decrypts the body of the msg using Wireguard private key and Remote peer's public key
func (client *Client) Send(msg *proto.Message) error { func (c *Client) decryptMessage(msg *proto.EncryptedMessage) (*proto.Message, error) {
remoteKey, err := wgtypes.ParseKey(msg.GetKey())
if err != nil {
return nil, err
}
decryptedBody, err := Decrypt(msg.GetBody(), c.key, remoteKey)
body := &proto.Body{}
err = pb.Unmarshal(decryptedBody, body)
if err != nil {
return nil, err
}
_, err := client.realClient.Connect(context.TODO(), msg) return &proto.Message{
Key: msg.Key,
RemoteKey: msg.RemoteKey,
Body: body,
}, nil
}
// encryptMessage encrypts the body of the msg using Wireguard private key and Remote peer's public key
func (c *Client) encryptMessage(msg *proto.Message) (*proto.EncryptedMessage, error) {
body, err := pb.Marshal(msg.GetBody())
if err != nil {
return nil, err
}
remoteKey, err := wgtypes.ParseKey(msg.RemoteKey)
if err != nil {
return nil, err
}
encryptedBody, err := Encrypt(body, c.key, remoteKey)
if err != nil {
return nil, err
}
return &proto.EncryptedMessage{
Key: msg.GetKey(),
RemoteKey: msg.GetRemoteKey(),
Body: encryptedBody,
}, nil
}
// Sends a message to the remote Peer through the Signal Exchange.
func (c *Client) Send(msg *proto.Message) error {
encryptedMessage, err := c.encryptMessage(msg)
if err != nil {
return err
}
_, err = c.realClient.Send(context.TODO(), encryptedMessage)
if err != nil { if err != nil {
log.Errorf("error while sending message to peer [%s] [error: %v]", msg.RemoteKey, err) log.Errorf("error while sending message to peer [%s] [error: %v]", msg.RemoteKey, err)
return err return err
@ -155,7 +206,7 @@ func (client *Client) Send(msg *proto.Message) error {
} }
// Receives messages from other peers coming through the Signal Exchange // Receives messages from other peers coming through the Signal Exchange
func (client *Client) receive(stream proto.SignalExchange_ConnectStreamClient, func (c *Client) receive(stream proto.SignalExchange_ConnectStreamClient,
msgHandler func(msg *proto.Message) error) error { msgHandler func(msg *proto.Message) error) error {
for { for {
@ -172,10 +223,14 @@ func (client *Client) receive(stream proto.SignalExchange_ConnectStreamClient,
} else if err != nil { } else if err != nil {
return err return err
} }
log.Debugf("received a new message from Peer [fingerprint: %s] [type %s]", msg.Key, msg.Type) log.Debugf("received a new message from Peer [fingerprint: %s]", msg.Key)
//todo decrypt decryptedMessage, err := c.decryptMessage(msg)
err = msgHandler(msg) if err != nil {
log.Errorf("failed decrypting message of Peer [key: %s] error: [%s]", msg.Key, err.Error())
}
err = msgHandler(decryptedMessage)
if err != nil { if err != nil {
log.Errorf("error while handling message of Peer [key: %s] error: [%s]", msg.Key, err.Error()) log.Errorf("error while handling message of Peer [key: %s] error: [%s]", msg.Key, err.Error())
@ -185,7 +240,8 @@ func (client *Client) receive(stream proto.SignalExchange_ConnectStreamClient,
} }
func UnMarshalCredential(msg *proto.Message) (*Credential, error) { func UnMarshalCredential(msg *proto.Message) (*Credential, error) {
credential := strings.Split(msg.Body, ":")
credential := strings.Split(msg.GetBody().GetPayload(), ":")
if len(credential) != 2 { if len(credential) != 2 {
return nil, fmt.Errorf("error parsing message body %s", msg.Body) return nil, fmt.Errorf("error parsing message body %s", msg.Body)
} }
@ -195,13 +251,15 @@ func UnMarshalCredential(msg *proto.Message) (*Credential, error) {
}, nil }, nil
} }
func MarshalCredential(ourKey string, remoteKey string, credential *Credential, t proto.Message_Type) *proto.Message { func MarshalCredential(myKey wgtypes.Key, remoteKey wgtypes.Key, credential *Credential, t proto.Body_Type) (*proto.Message, error) {
return &proto.Message{ return &proto.Message{
Type: t, Key: myKey.PublicKey().String(),
Key: ourKey, RemoteKey: remoteKey.String(),
RemoteKey: remoteKey, Body: &proto.Body{
Body: fmt.Sprintf("%s:%s", credential.UFrag, credential.Pwd), Type: t,
} Payload: fmt.Sprintf("%s:%s", credential.UFrag, credential.Pwd),
},
}, nil
} }
type Credential struct { type Credential struct {

View File

@ -13,7 +13,7 @@ import (
// Wireguard keys are used for encryption // Wireguard keys are used for encryption
// Encrypts a message using local Wireguard private key and remote peer's public key. // Encrypts a message using local Wireguard private key and remote peer's public key.
func EncryptMessage(msg []byte, privateKey wgtypes.Key, remotePubKey wgtypes.Key) ([]byte, error) { func Encrypt(msg []byte, privateKey wgtypes.Key, remotePubKey wgtypes.Key) ([]byte, error) {
nonce, err := genNonce() nonce, err := genNonce()
if err != nil { if err != nil {
return nil, err return nil, err
@ -23,7 +23,7 @@ func EncryptMessage(msg []byte, privateKey wgtypes.Key, remotePubKey wgtypes.Key
} }
// Decrypts a message that has been encrypted by the remote peer using Wireguard private key and remote peer's public key. // Decrypts a message that has been encrypted by the remote peer using Wireguard private key and remote peer's public key.
func DecryptMessage(encryptedMsg []byte, privateKey wgtypes.Key, remotePubKey wgtypes.Key) ([]byte, error) { func Decrypt(encryptedMsg []byte, privateKey wgtypes.Key, remotePubKey wgtypes.Key) ([]byte, error) {
nonce, err := genNonce() nonce, err := genNonce()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -26,41 +26,101 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// Message type // Message type
type Message_Type int32 type Body_Type int32
const ( const (
Message_OFFER Message_Type = 0 Body_OFFER Body_Type = 0
Message_ANSWER Message_Type = 1 Body_ANSWER Body_Type = 1
Message_CANDIDATE Message_Type = 2 Body_CANDIDATE Body_Type = 2
) )
var Message_Type_name = map[int32]string{ var Body_Type_name = map[int32]string{
0: "OFFER", 0: "OFFER",
1: "ANSWER", 1: "ANSWER",
2: "CANDIDATE", 2: "CANDIDATE",
} }
var Message_Type_value = map[string]int32{ var Body_Type_value = map[string]int32{
"OFFER": 0, "OFFER": 0,
"ANSWER": 1, "ANSWER": 1,
"CANDIDATE": 2, "CANDIDATE": 2,
} }
func (x Message_Type) String() string { func (x Body_Type) String() string {
return proto.EnumName(Message_Type_name, int32(x)) return proto.EnumName(Body_Type_name, int32(x))
} }
func (Message_Type) EnumDescriptor() ([]byte, []int) { func (Body_Type) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_bf680d70b8e3473f, []int{0, 0} return fileDescriptor_bf680d70b8e3473f, []int{2, 0}
} }
// Used for sending through signal.
// The body of this message is the Body message encrypted with the Wireguard private key and the remote Peer key
type EncryptedMessage struct {
// a sha256 fingerprint of the Wireguard public key
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
// a sha256 fingerprint of the Wireguard public key of the remote peer to connect to
RemoteKey string `protobuf:"bytes,3,opt,name=remoteKey,proto3" json:"remoteKey,omitempty"`
// encrypted message body
Body []byte `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *EncryptedMessage) Reset() { *m = EncryptedMessage{} }
func (m *EncryptedMessage) String() string { return proto.CompactTextString(m) }
func (*EncryptedMessage) ProtoMessage() {}
func (*EncryptedMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_bf680d70b8e3473f, []int{0}
}
func (m *EncryptedMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EncryptedMessage.Unmarshal(m, b)
}
func (m *EncryptedMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_EncryptedMessage.Marshal(b, m, deterministic)
}
func (m *EncryptedMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_EncryptedMessage.Merge(m, src)
}
func (m *EncryptedMessage) XXX_Size() int {
return xxx_messageInfo_EncryptedMessage.Size(m)
}
func (m *EncryptedMessage) XXX_DiscardUnknown() {
xxx_messageInfo_EncryptedMessage.DiscardUnknown(m)
}
var xxx_messageInfo_EncryptedMessage proto.InternalMessageInfo
func (m *EncryptedMessage) GetKey() string {
if m != nil {
return m.Key
}
return ""
}
func (m *EncryptedMessage) GetRemoteKey() string {
if m != nil {
return m.RemoteKey
}
return ""
}
func (m *EncryptedMessage) GetBody() []byte {
if m != nil {
return m.Body
}
return nil
}
// A decrypted representation of the EncryptedMessage. Used locally before/after encryption
type Message struct { type Message struct {
Type Message_Type `protobuf:"varint,1,opt,name=type,proto3,enum=signalexchange.Message_Type" json:"type,omitempty"`
// a sha256 fingerprint of the Wireguard public key // a sha256 fingerprint of the Wireguard public key
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
// a sha256 fingerprint of the Wireguard public key of the remote peer to connect to // a sha256 fingerprint of the Wireguard public key of the remote peer to connect to
RemoteKey string `protobuf:"bytes,3,opt,name=remoteKey,proto3" json:"remoteKey,omitempty"` RemoteKey string `protobuf:"bytes,3,opt,name=remoteKey,proto3" json:"remoteKey,omitempty"`
Body string `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"` Body *Body `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -70,7 +130,7 @@ func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) } func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {} func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) { func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_bf680d70b8e3473f, []int{0} return fileDescriptor_bf680d70b8e3473f, []int{1}
} }
func (m *Message) XXX_Unmarshal(b []byte) error { func (m *Message) XXX_Unmarshal(b []byte) error {
@ -91,13 +151,6 @@ func (m *Message) XXX_DiscardUnknown() {
var xxx_messageInfo_Message proto.InternalMessageInfo var xxx_messageInfo_Message proto.InternalMessageInfo
func (m *Message) GetType() Message_Type {
if m != nil {
return m.Type
}
return Message_OFFER
}
func (m *Message) GetKey() string { func (m *Message) GetKey() string {
if m != nil { if m != nil {
return m.Key return m.Key
@ -112,39 +165,93 @@ func (m *Message) GetRemoteKey() string {
return "" return ""
} }
func (m *Message) GetBody() string { func (m *Message) GetBody() *Body {
if m != nil { if m != nil {
return m.Body return m.Body
} }
return nil
}
// Actual body of the message that can contain credentials (type OFFER/ANSWER) or connection Candidate
// This part will be encrypted
type Body struct {
Type Body_Type `protobuf:"varint,1,opt,name=type,proto3,enum=signalexchange.Body_Type" json:"type,omitempty"`
Payload string `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Body) Reset() { *m = Body{} }
func (m *Body) String() string { return proto.CompactTextString(m) }
func (*Body) ProtoMessage() {}
func (*Body) Descriptor() ([]byte, []int) {
return fileDescriptor_bf680d70b8e3473f, []int{2}
}
func (m *Body) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Body.Unmarshal(m, b)
}
func (m *Body) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Body.Marshal(b, m, deterministic)
}
func (m *Body) XXX_Merge(src proto.Message) {
xxx_messageInfo_Body.Merge(m, src)
}
func (m *Body) XXX_Size() int {
return xxx_messageInfo_Body.Size(m)
}
func (m *Body) XXX_DiscardUnknown() {
xxx_messageInfo_Body.DiscardUnknown(m)
}
var xxx_messageInfo_Body proto.InternalMessageInfo
func (m *Body) GetType() Body_Type {
if m != nil {
return m.Type
}
return Body_OFFER
}
func (m *Body) GetPayload() string {
if m != nil {
return m.Payload
}
return "" return ""
} }
func init() { func init() {
proto.RegisterEnum("signalexchange.Message_Type", Message_Type_name, Message_Type_value) proto.RegisterEnum("signalexchange.Body_Type", Body_Type_name, Body_Type_value)
proto.RegisterType((*EncryptedMessage)(nil), "signalexchange.EncryptedMessage")
proto.RegisterType((*Message)(nil), "signalexchange.Message") proto.RegisterType((*Message)(nil), "signalexchange.Message")
proto.RegisterType((*Body)(nil), "signalexchange.Body")
} }
func init() { proto.RegisterFile("signalexchange.proto", fileDescriptor_bf680d70b8e3473f) } func init() { proto.RegisterFile("signalexchange.proto", fileDescriptor_bf680d70b8e3473f) }
var fileDescriptor_bf680d70b8e3473f = []byte{ var fileDescriptor_bf680d70b8e3473f = []byte{
// 272 bytes of a gzipped FileDescriptorProto // 319 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x50, 0xcd, 0x4a, 0xf3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x52, 0x4f, 0x4b, 0xfb, 0x40,
0x14, 0xed, 0xb4, 0xf9, 0x1a, 0x72, 0xa1, 0x21, 0x5c, 0x3e, 0x30, 0x94, 0x2e, 0x42, 0x56, 0x59, 0x10, 0xed, 0xb6, 0xf9, 0xb5, 0x64, 0x7e, 0xb6, 0x84, 0xa1, 0x87, 0x58, 0x3c, 0x84, 0x9c, 0x72,
0x48, 0x5a, 0xea, 0x52, 0x5c, 0xc4, 0x36, 0x15, 0x11, 0x2b, 0x24, 0x05, 0xc1, 0x5d, 0x9a, 0x5e, 0xd0, 0x54, 0xea, 0xd1, 0x53, 0xff, 0xa4, 0x20, 0x6a, 0x85, 0xa4, 0x28, 0x7a, 0x4b, 0x93, 0x31,
0xc7, 0x62, 0x9b, 0x09, 0x93, 0x11, 0x9c, 0x37, 0xf1, 0x25, 0x7c, 0x47, 0xe9, 0x34, 0x20, 0x0a, 0x16, 0xdb, 0x6c, 0xd8, 0xac, 0xe0, 0x1e, 0xfc, 0x60, 0x7e, 0x3b, 0xe9, 0xb6, 0xa2, 0x06, 0x41,
0xdd, 0xb8, 0x9a, 0xc3, 0xf9, 0x9b, 0xc3, 0x85, 0xff, 0xcd, 0x96, 0x57, 0xc5, 0x8e, 0xde, 0xcb, 0x10, 0x4f, 0x3b, 0xf3, 0xf6, 0xcd, 0x7b, 0x6f, 0x97, 0x81, 0x6e, 0xb9, 0xcc, 0xf2, 0x78, 0x45,
0x97, 0xa2, 0xe2, 0x14, 0xd7, 0x52, 0x28, 0x81, 0xee, 0x4f, 0x76, 0x18, 0x70, 0x21, 0xf8, 0x8e, 0xcf, 0xc9, 0x43, 0x9c, 0x67, 0xe4, 0x17, 0x82, 0x4b, 0x8e, 0x9d, 0xaf, 0x68, 0xcf, 0xc9, 0x38,
0xc6, 0x46, 0x5d, 0xbf, 0x3d, 0x8f, 0x37, 0xd4, 0x94, 0x72, 0x5b, 0x2b, 0x21, 0x8f, 0x89, 0xf0, 0xcf, 0x56, 0xd4, 0xd7, 0xb7, 0x8b, 0xa7, 0xfb, 0x7e, 0x4a, 0x65, 0x22, 0x96, 0x85, 0xe4, 0x62,
0x93, 0x81, 0x7d, 0x4f, 0x4d, 0x53, 0x70, 0xc2, 0x09, 0x58, 0x4a, 0xd7, 0xe4, 0xb3, 0x80, 0x45, 0x3b, 0xe1, 0x5e, 0x83, 0x15, 0xe4, 0x89, 0x50, 0x85, 0xa4, 0xf4, 0x92, 0xca, 0x32, 0xce, 0x08,
0xee, 0x74, 0x14, 0xff, 0xfa, 0xa2, 0xb5, 0xc5, 0x2b, 0x5d, 0x53, 0x66, 0x9c, 0xe8, 0x41, 0xef, 0x2d, 0x68, 0x3c, 0x92, 0xb2, 0xeb, 0x0e, 0xf3, 0xcc, 0x70, 0x53, 0xe2, 0x01, 0x98, 0x82, 0xd6,
0x95, 0xb4, 0xdf, 0x0d, 0x58, 0xe4, 0x64, 0x07, 0x88, 0x23, 0x70, 0x24, 0xed, 0x85, 0xa2, 0x3b, 0x5c, 0xd2, 0x39, 0x29, 0xbb, 0xa1, 0xf1, 0x0f, 0x00, 0x11, 0x8c, 0x05, 0x4f, 0x95, 0x6d, 0x38,
0xd2, 0x7e, 0xcf, 0xf0, 0xdf, 0x04, 0x22, 0x58, 0x6b, 0xb1, 0xd1, 0xbe, 0x65, 0x04, 0x83, 0xc3, 0xcc, 0xdb, 0x0b, 0x75, 0xed, 0x26, 0xd0, 0xfa, 0xad, 0x9c, 0xf7, 0x49, 0xee, 0xff, 0xa0, 0xeb,
0x73, 0xb0, 0x0e, 0x8d, 0xe8, 0xc0, 0xbf, 0x87, 0xc5, 0x22, 0xcd, 0xbc, 0x0e, 0x02, 0xf4, 0x93, 0x57, 0x5e, 0x3a, 0xe2, 0xa9, 0xda, 0x99, 0xbc, 0x80, 0xb1, 0xe9, 0xf0, 0x08, 0x0c, 0xa9, 0x0a,
0x65, 0xfe, 0x98, 0x66, 0x1e, 0xc3, 0x01, 0x38, 0xb3, 0x64, 0x39, 0xbf, 0x9d, 0x27, 0xab, 0xd4, 0xb2, 0x99, 0xc3, 0xbc, 0xce, 0x60, 0xff, 0xbb, 0x09, 0x7f, 0xae, 0x0a, 0x0a, 0x35, 0x0d, 0x6d,
0xeb, 0x4e, 0x3f, 0x18, 0xb8, 0xb9, 0xd9, 0x95, 0xb6, 0xbb, 0xf0, 0x0a, 0xec, 0x99, 0xa8, 0x2a, 0x68, 0x15, 0xb1, 0x5a, 0xf1, 0x38, 0xdd, 0x85, 0x7a, 0x6f, 0xdd, 0x43, 0x30, 0x36, 0x3c, 0x34,
0x2a, 0x15, 0x9e, 0x9d, 0xd8, 0x3c, 0x3c, 0x25, 0x84, 0x1d, 0xbc, 0x81, 0x41, 0x1b, 0xcf, 0x95, 0xe1, 0xdf, 0xd5, 0x74, 0x1a, 0x84, 0x56, 0x0d, 0x01, 0x9a, 0xc3, 0x59, 0x74, 0x13, 0x84, 0x16,
0xa4, 0x62, 0xff, 0x97, 0x92, 0x88, 0x4d, 0xd8, 0xb5, 0xf3, 0x64, 0xc7, 0x97, 0xc7, 0x4b, 0xf7, 0xc3, 0x36, 0x98, 0xe3, 0xe1, 0x6c, 0x72, 0x36, 0x19, 0xce, 0x03, 0xab, 0x3e, 0x78, 0x65, 0xd0,
0xcd, 0x73, 0xf1, 0x15, 0x00, 0x00, 0xff, 0xff, 0x20, 0x13, 0xc1, 0xe1, 0xa6, 0x01, 0x00, 0x00, 0x89, 0xb4, 0x55, 0xb0, 0xb3, 0xc2, 0x0b, 0x30, 0x22, 0xca, 0x53, 0x74, 0xaa, 0x19, 0xaa, 0x9f,
0xdc, 0xfb, 0x91, 0xe1, 0xd6, 0xf0, 0x16, 0xda, 0x63, 0x9e, 0xe7, 0x94, 0xc8, 0x48, 0x0a, 0x8a,
0xd7, 0x7f, 0x23, 0xeb, 0xb1, 0x63, 0x36, 0x32, 0xef, 0x5a, 0xfe, 0xe9, 0x76, 0x2d, 0x9a, 0xfa,
0x38, 0x79, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xb8, 0xb5, 0xbf, 0xeb, 0x53, 0x02, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -160,7 +267,7 @@ const _ = grpc.SupportPackageIsVersion4
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type SignalExchangeClient interface { type SignalExchangeClient interface {
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer) // Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
Connect(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) Send(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error)
// Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer) // Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer)
ConnectStream(ctx context.Context, opts ...grpc.CallOption) (SignalExchange_ConnectStreamClient, error) ConnectStream(ctx context.Context, opts ...grpc.CallOption) (SignalExchange_ConnectStreamClient, error)
} }
@ -173,9 +280,9 @@ func NewSignalExchangeClient(cc *grpc.ClientConn) SignalExchangeClient {
return &signalExchangeClient{cc} return &signalExchangeClient{cc}
} }
func (c *signalExchangeClient) Connect(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) { func (c *signalExchangeClient) Send(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
out := new(Message) out := new(EncryptedMessage)
err := c.cc.Invoke(ctx, "/signalexchange.SignalExchange/Connect", in, out, opts...) err := c.cc.Invoke(ctx, "/signalexchange.SignalExchange/Send", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -192,8 +299,8 @@ func (c *signalExchangeClient) ConnectStream(ctx context.Context, opts ...grpc.C
} }
type SignalExchange_ConnectStreamClient interface { type SignalExchange_ConnectStreamClient interface {
Send(*Message) error Send(*EncryptedMessage) error
Recv() (*Message, error) Recv() (*EncryptedMessage, error)
grpc.ClientStream grpc.ClientStream
} }
@ -201,12 +308,12 @@ type signalExchangeConnectStreamClient struct {
grpc.ClientStream grpc.ClientStream
} }
func (x *signalExchangeConnectStreamClient) Send(m *Message) error { func (x *signalExchangeConnectStreamClient) Send(m *EncryptedMessage) error {
return x.ClientStream.SendMsg(m) return x.ClientStream.SendMsg(m)
} }
func (x *signalExchangeConnectStreamClient) Recv() (*Message, error) { func (x *signalExchangeConnectStreamClient) Recv() (*EncryptedMessage, error) {
m := new(Message) m := new(EncryptedMessage)
if err := x.ClientStream.RecvMsg(m); err != nil { if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err return nil, err
} }
@ -216,7 +323,7 @@ func (x *signalExchangeConnectStreamClient) Recv() (*Message, error) {
// SignalExchangeServer is the server API for SignalExchange service. // SignalExchangeServer is the server API for SignalExchange service.
type SignalExchangeServer interface { type SignalExchangeServer interface {
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer) // Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
Connect(context.Context, *Message) (*Message, error) Send(context.Context, *EncryptedMessage) (*EncryptedMessage, error)
// Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer) // Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer)
ConnectStream(SignalExchange_ConnectStreamServer) error ConnectStream(SignalExchange_ConnectStreamServer) error
} }
@ -225,8 +332,8 @@ type SignalExchangeServer interface {
type UnimplementedSignalExchangeServer struct { type UnimplementedSignalExchangeServer struct {
} }
func (*UnimplementedSignalExchangeServer) Connect(ctx context.Context, req *Message) (*Message, error) { func (*UnimplementedSignalExchangeServer) Send(ctx context.Context, req *EncryptedMessage) (*EncryptedMessage, error) {
return nil, status.Errorf(codes.Unimplemented, "method Connect not implemented") return nil, status.Errorf(codes.Unimplemented, "method Send not implemented")
} }
func (*UnimplementedSignalExchangeServer) ConnectStream(srv SignalExchange_ConnectStreamServer) error { func (*UnimplementedSignalExchangeServer) ConnectStream(srv SignalExchange_ConnectStreamServer) error {
return status.Errorf(codes.Unimplemented, "method ConnectStream not implemented") return status.Errorf(codes.Unimplemented, "method ConnectStream not implemented")
@ -236,20 +343,20 @@ func RegisterSignalExchangeServer(s *grpc.Server, srv SignalExchangeServer) {
s.RegisterService(&_SignalExchange_serviceDesc, srv) s.RegisterService(&_SignalExchange_serviceDesc, srv)
} }
func _SignalExchange_Connect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _SignalExchange_Send_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Message) in := new(EncryptedMessage)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
if interceptor == nil { if interceptor == nil {
return srv.(SignalExchangeServer).Connect(ctx, in) return srv.(SignalExchangeServer).Send(ctx, in)
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/signalexchange.SignalExchange/Connect", FullMethod: "/signalexchange.SignalExchange/Send",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SignalExchangeServer).Connect(ctx, req.(*Message)) return srv.(SignalExchangeServer).Send(ctx, req.(*EncryptedMessage))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
@ -259,8 +366,8 @@ func _SignalExchange_ConnectStream_Handler(srv interface{}, stream grpc.ServerSt
} }
type SignalExchange_ConnectStreamServer interface { type SignalExchange_ConnectStreamServer interface {
Send(*Message) error Send(*EncryptedMessage) error
Recv() (*Message, error) Recv() (*EncryptedMessage, error)
grpc.ServerStream grpc.ServerStream
} }
@ -268,12 +375,12 @@ type signalExchangeConnectStreamServer struct {
grpc.ServerStream grpc.ServerStream
} }
func (x *signalExchangeConnectStreamServer) Send(m *Message) error { func (x *signalExchangeConnectStreamServer) Send(m *EncryptedMessage) error {
return x.ServerStream.SendMsg(m) return x.ServerStream.SendMsg(m)
} }
func (x *signalExchangeConnectStreamServer) Recv() (*Message, error) { func (x *signalExchangeConnectStreamServer) Recv() (*EncryptedMessage, error) {
m := new(Message) m := new(EncryptedMessage)
if err := x.ServerStream.RecvMsg(m); err != nil { if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err return nil, err
} }
@ -285,8 +392,8 @@ var _SignalExchange_serviceDesc = grpc.ServiceDesc{
HandlerType: (*SignalExchangeServer)(nil), HandlerType: (*SignalExchangeServer)(nil),
Methods: []grpc.MethodDesc{ Methods: []grpc.MethodDesc{
{ {
MethodName: "Connect", MethodName: "Send",
Handler: _SignalExchange_Connect_Handler, Handler: _SignalExchange_Send_Handler,
}, },
}, },
Streams: []grpc.StreamDesc{ Streams: []grpc.StreamDesc{

View File

@ -8,27 +8,45 @@ package signalexchange;
service SignalExchange { service SignalExchange {
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer) // Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
rpc Connect(Message) returns (Message) {} rpc Send(EncryptedMessage) returns (EncryptedMessage) {}
// Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer) // Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer)
rpc ConnectStream(stream Message) returns (stream Message) {} rpc ConnectStream(stream EncryptedMessage) returns (stream EncryptedMessage) {}
} }
message Message { // Used for sending through signal.
// The body of this message is the Body message encrypted with the Wireguard private key and the remote Peer key
message EncryptedMessage {
// Wireguard public key
string key = 2;
// Wireguard public key of the remote peer to connect to
string remoteKey = 3;
// encrypted message Body
bytes body = 4;
}
// A decrypted representation of the EncryptedMessage. Used locally before/after encryption
message Message {
// Wireguard public key
string key = 2;
// Wireguard public key of the remote peer to connect to
string remoteKey = 3;
Body body = 4;
}
// Actual body of the message that can contain credentials (type OFFER/ANSWER) or connection Candidate
// This part will be encrypted
message Body {
// Message type // Message type
enum Type { enum Type {
OFFER = 0; OFFER = 0;
ANSWER = 1; ANSWER = 1;
CANDIDATE = 2; CANDIDATE = 2;
} }
Type type = 1; Type type = 1;
string payload = 2;
// a sha256 fingerprint of the Wireguard public key
string key = 2;
// a sha256 fingerprint of the Wireguard public key of the remote peer to connect to
string remoteKey = 3;
string body = 4;
} }

View File

@ -27,7 +27,7 @@ func NewServer() *SignalExchangeServer {
} }
} }
func (s *SignalExchangeServer) Connect(ctx context.Context, msg *proto.Message) (*proto.Message, error) { func (s *SignalExchangeServer) Send(ctx context.Context, msg *proto.EncryptedMessage) (*proto.Message, error) {
if _, found := s.registry.Peers[msg.Key]; !found { if _, found := s.registry.Peers[msg.Key]; !found {
return nil, fmt.Errorf("unknown peer %s", msg.Key) return nil, fmt.Errorf("unknown peer %s", msg.Key)