|
1 | 1 | package core
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "crypto/rand" |
4 | 5 | "errors"
|
5 | 6 | "fmt"
|
| 7 | + "gx/ipfs/QmUadX5EcvrBmxAV9sE7wUWtWSqxns5K84qKJBixmcT1w9/go-datastore" |
| 8 | + "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing" |
6 | 9 | "sync"
|
7 | 10 | "time"
|
8 | 11 |
|
| 12 | + "golang.org/x/crypto/nacl/box" |
| 13 | + |
9 | 14 | libp2p "gx/ipfs/QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK/go-libp2p-crypto"
|
10 | 15 | "gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid"
|
11 |
| - peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" |
12 |
| - "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash" |
| 16 | + "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer" |
13 | 17 |
|
14 |
| - "github.com/OpenBazaar/openbazaar-go/ipfs" |
15 | 18 | "github.com/OpenBazaar/openbazaar-go/pb"
|
16 | 19 | "github.com/OpenBazaar/openbazaar-go/repo"
|
17 | 20 | "github.com/golang/protobuf/proto"
|
@@ -70,64 +73,111 @@ func (n *OpenBazaarNode) SendOfflineMessage(p peer.ID, k *libp2p.PubKey, m *pb.M
|
70 | 73 | if merr != nil {
|
71 | 74 | return merr
|
72 | 75 | }
|
73 |
| - // TODO: this function blocks if the recipient's public key is not on the local machine |
74 |
| - ciphertext, cerr := n.EncryptMessage(p, k, messageBytes) |
75 |
| - if cerr != nil { |
76 |
| - return cerr |
77 |
| - } |
78 |
| - addr, aerr := n.MessageStorage.Store(p, ciphertext) |
79 |
| - if aerr != nil { |
80 |
| - return aerr |
81 |
| - } |
82 |
| - mh, mherr := multihash.FromB58String(p.Pretty()) |
83 |
| - if mherr != nil { |
84 |
| - return mherr |
85 |
| - } |
86 |
| - /* TODO: We are just using a default prefix length for now. Eventually we will want to customize this, |
87 |
| - but we will need some way to get the recipient's desired prefix length. Likely will be in profile. */ |
88 |
| - pointer, err := ipfs.NewPointer(mh, DefaultPointerPrefixLength, addr, ciphertext) |
89 |
| - if err != nil { |
90 |
| - return err |
91 |
| - } |
92 |
| - if m.MessageType != pb.Message_OFFLINE_ACK { |
93 |
| - pointer.Purpose = ipfs.MESSAGE |
94 |
| - pointer.CancelID = &p |
95 |
| - err = n.Datastore.Pointers().Put(pointer) |
96 |
| - if err != nil { |
97 |
| - return err |
98 |
| - } |
99 |
| - } |
100 |
| - log.Debugf("Sending offline message to: %s, Message Type: %s, PointerID: %s, Location: %s", p.Pretty(), m.MessageType.String(), pointer.Cid.String(), pointer.Value.Addrs[0].String()) |
101 |
| - OfflineMessageWaitGroup.Add(2) |
102 |
| - go func() { |
103 |
| - ctx, cancel := context.WithCancel(context.Background()) |
104 |
| - defer cancel() |
105 |
| - err := ipfs.PublishPointer(n.DHT, ctx, pointer) |
106 |
| - if err != nil { |
107 |
| - log.Error(err) |
108 |
| - } |
109 | 76 |
|
110 |
| - // Push provider to our push nodes for redundancy |
111 |
| - for _, p := range n.PushNodes { |
112 |
| - ctx, cancel := context.WithCancel(context.Background()) |
113 |
| - defer cancel() |
114 |
| - err := ipfs.PutPointerToPeer(n.DHT, ctx, p, pointer) |
| 77 | + // Encrypt envelope for relay server |
| 78 | + |
| 79 | + // Generate an ephemeral key pair |
| 80 | + _, ephemPriv, _ := box.GenerateKey(rand.Reader) |
| 81 | + |
| 82 | + ctx, cancel := context.WithTimeout(context.Background(), n.OfflineMessageFailoverTimeout) |
| 83 | + defer cancel() |
| 84 | + if k == nil { |
| 85 | + var pubKey libp2p.PubKey |
| 86 | + keyval, err := n.IpfsNode.Repo.Datastore().Get(datastore.NewKey(KeyCachePrefix + p.Pretty())) |
| 87 | + if err != nil { |
| 88 | + pubKey, err = routing.GetPublicKey(n.IpfsNode.Routing, ctx, p) |
115 | 89 | if err != nil {
|
116 |
| - log.Error(err) |
| 90 | + log.Errorf("Failed to find public key for %s", p.Pretty()) |
| 91 | + return err |
| 92 | + } |
| 93 | + } else { |
| 94 | + pubKey, err = libp2p.UnmarshalPublicKey(keyval) |
| 95 | + if err != nil { |
| 96 | + log.Errorf("Failed to find public key for %s", p.Pretty()) |
| 97 | + return err |
117 | 98 | }
|
118 | 99 | }
|
| 100 | + k = &pubKey |
| 101 | + } |
119 | 102 |
|
120 |
| - OfflineMessageWaitGroup.Done() |
121 |
| - }() |
122 |
| - go func() { |
123 |
| - ctx, cancel := context.WithCancel(context.Background()) |
124 |
| - defer cancel() |
125 |
| - err := n.Pubsub.Publisher.Publish(ctx, pointer.Cid.String(), ciphertext) |
126 |
| - if err != nil { |
127 |
| - log.Error(err) |
128 |
| - } |
129 |
| - OfflineMessageWaitGroup.Done() |
130 |
| - }() |
| 103 | + // Generate nonce |
| 104 | + var nonce [24]byte |
| 105 | + noncedata := make([]byte, 24) |
| 106 | + rand.Read(noncedata) |
| 107 | + for i := 0; i < 24; i++ { |
| 108 | + nonce[i] = noncedata[i] |
| 109 | + } |
| 110 | + |
| 111 | + // Encrypt |
| 112 | + var ciphertext []byte |
| 113 | + keybytes, _ := libp2p.MarshalPublicKey(*k) |
| 114 | + var pkey *[32]byte |
| 115 | + copy(pkey[:], keybytes[:32]) |
| 116 | + |
| 117 | + box.Seal(ciphertext, messageBytes, &nonce, pkey, ephemPriv) |
| 118 | + |
| 119 | + // TODO: this function blocks if the recipient's public key is not on the local machine |
| 120 | + //ciphertext, cerr := n.EncryptMessage(p, k, messageBytes) |
| 121 | + //if cerr != nil { |
| 122 | + // return cerr |
| 123 | + //} |
| 124 | + |
| 125 | + // Send to webrelay |
| 126 | + |
| 127 | + // |
| 128 | + //addr, aerr := n.MessageStorage.Store(p, ciphertext) |
| 129 | + //if aerr != nil { |
| 130 | + // return aerr |
| 131 | + //} |
| 132 | + //mh, mherr := multihash.FromB58String(p.Pretty()) |
| 133 | + //if mherr != nil { |
| 134 | + // return mherr |
| 135 | + //} |
| 136 | + ///* TODO: We are just using a default prefix length for now. Eventually we will want to customize this, |
| 137 | + // but we will need some way to get the recipient's desired prefix length. Likely will be in profile. */ |
| 138 | + //pointer, err := ipfs.NewPointer(mh, DefaultPointerPrefixLength, addr, ciphertext) |
| 139 | + //if err != nil { |
| 140 | + // return err |
| 141 | + //} |
| 142 | + //if m.MessageType != pb.Message_OFFLINE_ACK { |
| 143 | + // pointer.Purpose = ipfs.MESSAGE |
| 144 | + // pointer.CancelID = &p |
| 145 | + // err = n.Datastore.Pointers().Put(pointer) |
| 146 | + // if err != nil { |
| 147 | + // return err |
| 148 | + // } |
| 149 | + //} |
| 150 | + //log.Debugf("Sending offline message to: %s, Message Type: %s, PointerID: %s, Location: %s", p.Pretty(), m.MessageType.String(), pointer.Cid.String(), pointer.Value.Addrs[0].String()) |
| 151 | + //OfflineMessageWaitGroup.Add(2) |
| 152 | + //go func() { |
| 153 | + // ctx, cancel := context.WithCancel(context.Background()) |
| 154 | + // defer cancel() |
| 155 | + // err := ipfs.PublishPointer(n.DHT, ctx, pointer) |
| 156 | + // if err != nil { |
| 157 | + // log.Error(err) |
| 158 | + // } |
| 159 | + // |
| 160 | + // // Push provider to our push nodes for redundancy |
| 161 | + // for _, p := range n.PushNodes { |
| 162 | + // ctx, cancel := context.WithCancel(context.Background()) |
| 163 | + // defer cancel() |
| 164 | + // err := ipfs.PutPointerToPeer(n.DHT, ctx, p, pointer) |
| 165 | + // if err != nil { |
| 166 | + // log.Error(err) |
| 167 | + // } |
| 168 | + // } |
| 169 | + // |
| 170 | + // OfflineMessageWaitGroup.Done() |
| 171 | + //}() |
| 172 | + //go func() { |
| 173 | + // ctx, cancel := context.WithCancel(context.Background()) |
| 174 | + // defer cancel() |
| 175 | + // err := n.Pubsub.Publisher.Publish(ctx, pointer.Cid.String(), ciphertext) |
| 176 | + // if err != nil { |
| 177 | + // log.Error(err) |
| 178 | + // } |
| 179 | + // OfflineMessageWaitGroup.Done() |
| 180 | + //}() |
131 | 181 | return nil
|
132 | 182 | }
|
133 | 183 |
|
|
0 commit comments