Merge pull request #3 from wiretrustee/signal-encrypt

feat: add encryption of the payload exchanged via signal
This commit is contained in:
Mikhail Bragin 2021-05-05 10:42:31 +02:00 committed by GitHub
commit a15c8c9073
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 340 additions and 151 deletions

View File

@ -42,5 +42,5 @@ var (
)
func init() {
upCmd.PersistentFlags().IntVar(&port, "port", 10000, "Server port to listen on (e.g. 10000)")
signalCmd.PersistentFlags().IntVar(&port, "port", 10000, "Server port to listen on (e.g. 10000)")
}

View File

@ -6,9 +6,14 @@ import (
"github.com/spf13/cobra"
"github.com/wiretrustee/wiretrustee/connection"
sig "github.com/wiretrustee/wiretrustee/signal"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"os"
)
func toByte32(key wgtypes.Key) *[32]byte {
return (*[32]byte)(&key)
}
var (
upCmd = &cobra.Command{
Use: "up",
@ -18,8 +23,14 @@ var (
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()
signalClient, err := sig.NewClient(config.SignalAddr, ctx)
signalClient, err := sig.NewClient(config.SignalAddr, myKey, ctx)
if err != nil {
log.Errorf("error while connecting to the Signal Exchange Service %s: %s", config.SignalAddr, err)
os.Exit(ExitSetupFailed)
@ -29,7 +40,7 @@ var (
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()

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
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)
err := iface.Create(e.wgIface, e.wgIp)
if err != nil {
log.Errorf("error while creating interface %s: [%s]", e.wgIface, err.Error())
return err
@ -68,7 +60,7 @@ func (e *Engine) Start(privateKey string, peers []Peer) error {
return err
}
e.receiveSignal(myPubKey)
e.receiveSignal()
// initialize peer agents
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 {
err := s.Send(&sProto.Message{
Type: sProto.Message_CANDIDATE,
Key: myKey.PublicKey().String(),
RemoteKey: remoteKey.String(),
Body: candidate.Marshal(),
Body: &sProto.Body{
Type: sProto.Body_CANDIDATE,
Payload: candidate.Marshal(),
},
})
if err != nil {
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 {
var t sProto.Message_Type
var t sProto.Body_Type
if isAnswer {
t = sProto.Message_ANSWER
t = sProto.Body_ANSWER
} 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,
Pwd: pwd}, t)
err := s.Send(msg)
err = s.Send(msg)
if err != nil {
return err
}
@ -176,9 +170,9 @@ func signalAuth(uFrag string, pwd string, myKey wgtypes.Key, remoteKey wgtypes.K
return nil
}
func (e *Engine) receiveSignal(localKey string) {
func (e *Engine) receiveSignal() {
// connect to a stream of messages coming from the signal server
e.signal.Receive(localKey, func(msg *sProto.Message) error {
e.signal.Receive(func(msg *sProto.Message) error {
conn := e.conns[msg.Key]
if conn == nil {
@ -189,8 +183,8 @@ func (e *Engine) receiveSignal(localKey string) {
return fmt.Errorf("unknown peer %s", msg.Key)
}
switch msg.Type {
case sProto.Message_OFFER:
switch msg.GetBody().Type {
case sProto.Body_OFFER:
remoteCred, err := signal.UnMarshalCredential(msg)
if err != nil {
return err
@ -205,7 +199,7 @@ func (e *Engine) receiveSignal(localKey string) {
}
return nil
case sProto.Message_ANSWER:
case sProto.Body_ANSWER:
remoteCred, err := signal.UnMarshalCredential(msg)
if err != nil {
return err
@ -219,9 +213,9 @@ func (e *Engine) receiveSignal(localKey string) {
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 {
log.Errorf("failed on parsing remote candidate %s -> %s", candidate, err)
return err

View File

@ -4,8 +4,10 @@ import (
"context"
"fmt"
"github.com/cenkalti/backoff/v4"
pb "github.com/golang/protobuf/proto"
log "github.com/sirupsen/logrus"
"github.com/wiretrustee/wiretrustee/signal/proto"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/keepalive"
@ -21,20 +23,22 @@ import (
// Wraps the Signal Exchange Service gRpc client
type Client struct {
realClient proto.SignalExchangeClient
signalConn *grpc.ClientConn
ctx context.Context
stream proto.SignalExchange_ConnectStreamClient
key wgtypes.Key
encryptionKey string
realClient proto.SignalExchangeClient
signalConn *grpc.ClientConn
ctx context.Context
stream proto.SignalExchange_ConnectStreamClient
//waiting group to notify once stream is connected
connWg sync.WaitGroup //todo use a channel instead??
}
// Closes underlying connections to the Signal Exchange
func (client *Client) Close() error {
return client.signalConn.Close()
func (c *Client) Close() error {
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(
ctx,
@ -55,6 +59,7 @@ func NewClient(addr string, ctx context.Context) (*Client, error) {
realClient: proto.NewSignalExchangeClient(conn),
ctx: ctx,
signalConn: conn,
key: key,
}, nil
}
@ -62,8 +67,8 @@ func NewClient(addr string, ctx context.Context) (*Client, error) {
// 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)
// 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) {
client.connWg.Add(1)
func (c *Client) Receive(msgHandler func(msg *proto.Message) error) {
c.connWg.Add(1)
go func() {
var backOff = &backoff.ExponentialBackOff{
@ -77,10 +82,10 @@ func (client *Client) Receive(key string, msgHandler func(msg *proto.Message) er
}
operation := func() error {
err := client.connect(key, msgHandler)
err := c.connect(c.key.PublicKey().String(), msgHandler)
if err != nil {
log.Warnf("disconnected from the Signal Exchange due to an error %s. Retrying ... ", err)
client.connWg.Add(1)
c.connWg.Add(1)
return err
}
@ -96,44 +101,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 {
client.stream = nil
func (c *Client) connect(key string, msgHandler func(msg *proto.Message) error) error {
c.stream = nil
// add key fingerprint to the request header to be identified on the server side
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)
defer cancel()
stream, err := client.realClient.ConnectStream(ctx)
stream, err := c.realClient.ConnectStream(ctx)
client.stream = stream
c.stream = stream
if err != nil {
return err
}
//connection established we are good to use the stream
client.connWg.Done()
c.connWg.Done()
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
func (client *Client) WaitConnected() {
client.connWg.Wait()
func (c *Client) WaitConnected() {
c.connWg.Wait()
}
// 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
// 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")
}
err := client.stream.Send(msg)
err := c.stream.Send(msg)
if err != nil {
log.Errorf("error while sending message to peer [%s] [error: %v]", msg.RemoteKey, err)
return err
@ -142,10 +147,57 @@ func (client *Client) SendToStream(msg *proto.Message) error {
return nil
}
// Sends a message to the remote Peer through the Signal Exchange.
func (client *Client) Send(msg *proto.Message) error {
// decryptMessage decrypts the body of the msg using Wireguard private key and Remote peer's public key
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(), remoteKey, c.key)
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, remoteKey, c.key)
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 {
log.Errorf("error while sending message to peer [%s] [error: %v]", msg.RemoteKey, err)
return err
@ -155,7 +207,7 @@ func (client *Client) Send(msg *proto.Message) error {
}
// 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 {
for {
@ -172,10 +224,14 @@ func (client *Client) receive(stream proto.SignalExchange_ConnectStreamClient,
} else if err != nil {
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
err = msgHandler(msg)
decryptedMessage, err := c.decryptMessage(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 {
log.Errorf("error while handling message of Peer [key: %s] error: [%s]", msg.Key, err.Error())
@ -185,7 +241,8 @@ func (client *Client) receive(stream proto.SignalExchange_ConnectStreamClient,
}
func UnMarshalCredential(msg *proto.Message) (*Credential, error) {
credential := strings.Split(msg.Body, ":")
credential := strings.Split(msg.GetBody().GetPayload(), ":")
if len(credential) != 2 {
return nil, fmt.Errorf("error parsing message body %s", msg.Body)
}
@ -195,13 +252,15 @@ func UnMarshalCredential(msg *proto.Message) (*Credential, error) {
}, 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{
Type: t,
Key: ourKey,
RemoteKey: remoteKey,
Body: fmt.Sprintf("%s:%s", credential.UFrag, credential.Pwd),
}
Key: myKey.PublicKey().String(),
RemoteKey: remoteKey.String(),
Body: &proto.Body{
Type: t,
Payload: fmt.Sprintf("%s:%s", credential.UFrag, credential.Pwd),
},
}, nil
}
type Credential struct {

View File

@ -8,30 +8,30 @@ import (
)
// As set of tools to encrypt/decrypt messages being sent through the Signal Exchange Service.
// We want to make sure that the Connection Candidates and other irrelevant (to the Signal Exchange) information can't be read anywhere else but the Peer the message is being sent to.
// We want to make sure that the Connection Candidates and other irrelevant (to the Signal Exchange)
// information can't be read anywhere else but the Peer the message is being sent to.
// These tools use Golang crypto package (Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate)
// Wireguard keys are used for encryption
// 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, peersPublicKey wgtypes.Key, privateKey wgtypes.Key) ([]byte, error) {
nonce, err := genNonce()
if err != nil {
return nil, err
}
return box.Seal(nil, msg, nonce, toByte32(remotePubKey), toByte32(privateKey)), nil
return box.Seal(nonce[:], msg, nonce, toByte32(peersPublicKey), toByte32(privateKey)), nil
}
// 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, peersPublicKey wgtypes.Key, privateKey wgtypes.Key) ([]byte, error) {
nonce, err := genNonce()
if err != nil {
return nil, err
}
opened, ok := box.Open(nil, encryptedMsg, nonce, toByte32(remotePubKey), toByte32(privateKey))
copy(nonce[:], encryptedMsg[:24])
opened, ok := box.Open(nil, encryptedMsg[24:], nonce, toByte32(peersPublicKey), toByte32(privateKey))
if !ok {
return nil, fmt.Errorf("failed to decrypt message from peer %s", remotePubKey.String())
return nil, fmt.Errorf("failed to decrypt message from peer %s", peersPublicKey.String())
}
return opened, nil

View File

@ -26,41 +26,101 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// Message type
type Message_Type int32
type Body_Type int32
const (
Message_OFFER Message_Type = 0
Message_ANSWER Message_Type = 1
Message_CANDIDATE Message_Type = 2
Body_OFFER Body_Type = 0
Body_ANSWER Body_Type = 1
Body_CANDIDATE Body_Type = 2
)
var Message_Type_name = map[int32]string{
var Body_Type_name = map[int32]string{
0: "OFFER",
1: "ANSWER",
2: "CANDIDATE",
}
var Message_Type_value = map[string]int32{
var Body_Type_value = map[string]int32{
"OFFER": 0,
"ANSWER": 1,
"CANDIDATE": 2,
}
func (x Message_Type) String() string {
return proto.EnumName(Message_Type_name, int32(x))
func (x Body_Type) String() string {
return proto.EnumName(Body_Type_name, int32(x))
}
func (Message_Type) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_bf680d70b8e3473f, []int{0, 0}
func (Body_Type) EnumDescriptor() ([]byte, []int) {
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_Type `protobuf:"varint,1,opt,name=type,proto3,enum=signalexchange.Message_Type" json:"type,omitempty"`
// 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"`
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_unrecognized []byte `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 (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_bf680d70b8e3473f, []int{0}
return fileDescriptor_bf680d70b8e3473f, []int{1}
}
func (m *Message) XXX_Unmarshal(b []byte) error {
@ -91,13 +151,6 @@ func (m *Message) XXX_DiscardUnknown() {
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 {
if m != nil {
return m.Key
@ -112,39 +165,93 @@ func (m *Message) GetRemoteKey() string {
return ""
}
func (m *Message) GetBody() string {
func (m *Message) GetBody() *Body {
if m != nil {
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 ""
}
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((*Body)(nil), "signalexchange.Body")
}
func init() { proto.RegisterFile("signalexchange.proto", fileDescriptor_bf680d70b8e3473f) }
var fileDescriptor_bf680d70b8e3473f = []byte{
// 272 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x50, 0xcd, 0x4a, 0xf3, 0x40,
0x14, 0xed, 0xb4, 0xf9, 0x1a, 0x72, 0xa1, 0x21, 0x5c, 0x3e, 0x30, 0x94, 0x2e, 0x42, 0x56, 0x59,
0x48, 0x5a, 0xea, 0x52, 0x5c, 0xc4, 0x36, 0x15, 0x11, 0x2b, 0x24, 0x05, 0xc1, 0x5d, 0x9a, 0x5e,
0xc7, 0x62, 0x9b, 0x09, 0x93, 0x11, 0x9c, 0x37, 0xf1, 0x25, 0x7c, 0x47, 0xe9, 0x34, 0x20, 0x0a,
0xdd, 0xb8, 0x9a, 0xc3, 0xf9, 0x9b, 0xc3, 0x85, 0xff, 0xcd, 0x96, 0x57, 0xc5, 0x8e, 0xde, 0xcb,
0x97, 0xa2, 0xe2, 0x14, 0xd7, 0x52, 0x28, 0x81, 0xee, 0x4f, 0x76, 0x18, 0x70, 0x21, 0xf8, 0x8e,
0xc6, 0x46, 0x5d, 0xbf, 0x3d, 0x8f, 0x37, 0xd4, 0x94, 0x72, 0x5b, 0x2b, 0x21, 0x8f, 0x89, 0xf0,
0x93, 0x81, 0x7d, 0x4f, 0x4d, 0x53, 0x70, 0xc2, 0x09, 0x58, 0x4a, 0xd7, 0xe4, 0xb3, 0x80, 0x45,
0xee, 0x74, 0x14, 0xff, 0xfa, 0xa2, 0xb5, 0xc5, 0x2b, 0x5d, 0x53, 0x66, 0x9c, 0xe8, 0x41, 0xef,
0x95, 0xb4, 0xdf, 0x0d, 0x58, 0xe4, 0x64, 0x07, 0x88, 0x23, 0x70, 0x24, 0xed, 0x85, 0xa2, 0x3b,
0xd2, 0x7e, 0xcf, 0xf0, 0xdf, 0x04, 0x22, 0x58, 0x6b, 0xb1, 0xd1, 0xbe, 0x65, 0x04, 0x83, 0xc3,
0x73, 0xb0, 0x0e, 0x8d, 0xe8, 0xc0, 0xbf, 0x87, 0xc5, 0x22, 0xcd, 0xbc, 0x0e, 0x02, 0xf4, 0x93,
0x65, 0xfe, 0x98, 0x66, 0x1e, 0xc3, 0x01, 0x38, 0xb3, 0x64, 0x39, 0xbf, 0x9d, 0x27, 0xab, 0xd4,
0xeb, 0x4e, 0x3f, 0x18, 0xb8, 0xb9, 0xd9, 0x95, 0xb6, 0xbb, 0xf0, 0x0a, 0xec, 0x99, 0xa8, 0x2a,
0x2a, 0x15, 0x9e, 0x9d, 0xd8, 0x3c, 0x3c, 0x25, 0x84, 0x1d, 0xbc, 0x81, 0x41, 0x1b, 0xcf, 0x95,
0xa4, 0x62, 0xff, 0x97, 0x92, 0x88, 0x4d, 0xd8, 0xb5, 0xf3, 0x64, 0xc7, 0x97, 0xc7, 0x4b, 0xf7,
0xcd, 0x73, 0xf1, 0x15, 0x00, 0x00, 0xff, 0xff, 0x20, 0x13, 0xc1, 0xe1, 0xa6, 0x01, 0x00, 0x00,
// 319 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x52, 0x4f, 0x4b, 0xfb, 0x40,
0x10, 0xed, 0xb6, 0xf9, 0xb5, 0x64, 0x7e, 0xb6, 0x84, 0xa1, 0x87, 0x58, 0x3c, 0x84, 0x9c, 0x72,
0xd0, 0x54, 0xea, 0xd1, 0x53, 0xff, 0xa4, 0x20, 0x6a, 0x85, 0xa4, 0x28, 0x7a, 0x4b, 0x93, 0x31,
0x16, 0xdb, 0x6c, 0xd8, 0xac, 0xe0, 0x1e, 0xfc, 0x60, 0x7e, 0x3b, 0xe9, 0xb6, 0xa2, 0x06, 0x41,
0x10, 0x4f, 0x3b, 0xf3, 0xf6, 0xcd, 0x7b, 0x6f, 0x97, 0x81, 0x6e, 0xb9, 0xcc, 0xf2, 0x78, 0x45,
0xcf, 0xc9, 0x43, 0x9c, 0x67, 0xe4, 0x17, 0x82, 0x4b, 0x8e, 0x9d, 0xaf, 0x68, 0xcf, 0xc9, 0x38,
0xcf, 0x56, 0xd4, 0xd7, 0xb7, 0x8b, 0xa7, 0xfb, 0x7e, 0x4a, 0x65, 0x22, 0x96, 0x85, 0xe4, 0x62,
0x3b, 0xe1, 0x5e, 0x83, 0x15, 0xe4, 0x89, 0x50, 0x85, 0xa4, 0xf4, 0x92, 0xca, 0x32, 0xce, 0x08,
0x2d, 0x68, 0x3c, 0x92, 0xb2, 0xeb, 0x0e, 0xf3, 0xcc, 0x70, 0x53, 0xe2, 0x01, 0x98, 0x82, 0xd6,
0x5c, 0xd2, 0x39, 0x29, 0xbb, 0xa1, 0xf1, 0x0f, 0x00, 0x11, 0x8c, 0x05, 0x4f, 0x95, 0x6d, 0x38,
0xcc, 0xdb, 0x0b, 0x75, 0xed, 0x26, 0xd0, 0xfa, 0xad, 0x9c, 0xf7, 0x49, 0xee, 0xff, 0xa0, 0xeb,
0x57, 0x5e, 0x3a, 0xe2, 0xa9, 0xda, 0x99, 0xbc, 0x80, 0xb1, 0xe9, 0xf0, 0x08, 0x0c, 0xa9, 0x0a,
0xb2, 0x99, 0xc3, 0xbc, 0xce, 0x60, 0xff, 0xbb, 0x09, 0x7f, 0xae, 0x0a, 0x0a, 0x35, 0x0d, 0x6d,
0x68, 0x15, 0xb1, 0x5a, 0xf1, 0x38, 0xdd, 0x85, 0x7a, 0x6f, 0xdd, 0x43, 0x30, 0x36, 0x3c, 0x34,
0xe1, 0xdf, 0xd5, 0x74, 0x1a, 0x84, 0x56, 0x0d, 0x01, 0x9a, 0xc3, 0x59, 0x74, 0x13, 0x84, 0x16,
0xc3, 0x36, 0x98, 0xe3, 0xe1, 0x6c, 0x72, 0x36, 0x19, 0xce, 0x03, 0xab, 0x3e, 0x78, 0x65, 0xd0,
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.
@ -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.
type SignalExchangeClient interface {
// 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)
ConnectStream(ctx context.Context, opts ...grpc.CallOption) (SignalExchange_ConnectStreamClient, error)
}
@ -173,9 +280,9 @@ func NewSignalExchangeClient(cc *grpc.ClientConn) SignalExchangeClient {
return &signalExchangeClient{cc}
}
func (c *signalExchangeClient) Connect(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) {
out := new(Message)
err := c.cc.Invoke(ctx, "/signalexchange.SignalExchange/Connect", in, out, opts...)
func (c *signalExchangeClient) Send(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
out := new(EncryptedMessage)
err := c.cc.Invoke(ctx, "/signalexchange.SignalExchange/Send", in, out, opts...)
if err != nil {
return nil, err
}
@ -192,8 +299,8 @@ func (c *signalExchangeClient) ConnectStream(ctx context.Context, opts ...grpc.C
}
type SignalExchange_ConnectStreamClient interface {
Send(*Message) error
Recv() (*Message, error)
Send(*EncryptedMessage) error
Recv() (*EncryptedMessage, error)
grpc.ClientStream
}
@ -201,12 +308,12 @@ type signalExchangeConnectStreamClient struct {
grpc.ClientStream
}
func (x *signalExchangeConnectStreamClient) Send(m *Message) error {
func (x *signalExchangeConnectStreamClient) Send(m *EncryptedMessage) error {
return x.ClientStream.SendMsg(m)
}
func (x *signalExchangeConnectStreamClient) Recv() (*Message, error) {
m := new(Message)
func (x *signalExchangeConnectStreamClient) Recv() (*EncryptedMessage, error) {
m := new(EncryptedMessage)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
@ -216,7 +323,7 @@ func (x *signalExchangeConnectStreamClient) Recv() (*Message, error) {
// SignalExchangeServer is the server API for SignalExchange service.
type SignalExchangeServer interface {
// 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)
ConnectStream(SignalExchange_ConnectStreamServer) error
}
@ -225,8 +332,8 @@ type SignalExchangeServer interface {
type UnimplementedSignalExchangeServer struct {
}
func (*UnimplementedSignalExchangeServer) Connect(ctx context.Context, req *Message) (*Message, error) {
return nil, status.Errorf(codes.Unimplemented, "method Connect not implemented")
func (*UnimplementedSignalExchangeServer) Send(ctx context.Context, req *EncryptedMessage) (*EncryptedMessage, error) {
return nil, status.Errorf(codes.Unimplemented, "method Send not implemented")
}
func (*UnimplementedSignalExchangeServer) ConnectStream(srv SignalExchange_ConnectStreamServer) error {
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)
}
func _SignalExchange_Connect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Message)
func _SignalExchange_Send_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EncryptedMessage)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SignalExchangeServer).Connect(ctx, in)
return srv.(SignalExchangeServer).Send(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/signalexchange.SignalExchange/Connect",
FullMethod: "/signalexchange.SignalExchange/Send",
}
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)
}
@ -259,8 +366,8 @@ func _SignalExchange_ConnectStream_Handler(srv interface{}, stream grpc.ServerSt
}
type SignalExchange_ConnectStreamServer interface {
Send(*Message) error
Recv() (*Message, error)
Send(*EncryptedMessage) error
Recv() (*EncryptedMessage, error)
grpc.ServerStream
}
@ -268,12 +375,12 @@ type signalExchangeConnectStreamServer struct {
grpc.ServerStream
}
func (x *signalExchangeConnectStreamServer) Send(m *Message) error {
func (x *signalExchangeConnectStreamServer) Send(m *EncryptedMessage) error {
return x.ServerStream.SendMsg(m)
}
func (x *signalExchangeConnectStreamServer) Recv() (*Message, error) {
m := new(Message)
func (x *signalExchangeConnectStreamServer) Recv() (*EncryptedMessage, error) {
m := new(EncryptedMessage)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
@ -285,8 +392,8 @@ var _SignalExchange_serviceDesc = grpc.ServiceDesc{
HandlerType: (*SignalExchangeServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Connect",
Handler: _SignalExchange_Connect_Handler,
MethodName: "Send",
Handler: _SignalExchange_Send_Handler,
},
},
Streams: []grpc.StreamDesc{

View File

@ -8,27 +8,45 @@ package signalexchange;
service SignalExchange {
// 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)
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
enum Type {
OFFER = 0;
ANSWER = 1;
CANDIDATE = 2;
}
Type type = 1;
// 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;
string payload = 2;
}

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.EncryptedMessage, error) {
if _, found := s.registry.Peers[msg.Key]; !found {
return nil, fmt.Errorf("unknown peer %s", msg.Key)
@ -44,7 +44,7 @@ func (s *SignalExchangeServer) Connect(ctx context.Context, msg *proto.Message)
log.Warnf("message from peer [%s] can't be forwarded to peer [%s] because destination peer is not connected", msg.Key, msg.RemoteKey)
//todo respond to the sender?
}
return &proto.Message{}, nil
return &proto.EncryptedMessage{}, nil
}
func (s *SignalExchangeServer) ConnectStream(stream proto.SignalExchange_ConnectStreamServer) error {