-
Notifications
You must be signed in to change notification settings - Fork 8
/
encconn.go
87 lines (73 loc) · 2.04 KB
/
encconn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package encconn
import (
"bytes"
"encoding/binary"
"errors"
"net"
"golang.org/x/crypto/nacl/box"
)
// EncConn wraps net.Conn with box encryption
//
// NOTE: currently not working (as of August 2021)
type EncConn struct {
net.Conn
sharedSecret [32]byte
rxBuf bytes.Buffer
rxN, txN int
rxNonce, txNonce [24]byte
}
// NewEncConn wraps a net.Conn with a shared secret.
func NewEncConn(c net.Conn, sharedSecret [32]byte) *EncConn {
ec := &EncConn{
Conn: c,
sharedSecret: sharedSecret,
}
xorBy := sharedSecret[int(sharedSecret[0])%(len(sharedSecret)-1)]
ec.initNonce(ec.rxNonce[:], xorBy)
ec.initNonce(ec.txNonce[:], xorBy)
return ec
}
// Read reads data from the connection.
// Read can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *EncConn) Read(b []byte) (int, error) {
if c.rxBuf.Len() != 0 {
return c.rxBuf.Read(b)
}
var buf [1500]byte
n, err := c.Conn.Read(buf[:])
if err != nil {
return 0, err
}
c.incNonce(&c.rxN, c.rxNonce[:])
d, ok := box.OpenAfterPrecomputation(nil, buf[:n], &c.rxNonce, &c.sharedSecret)
if !ok {
return 0, errors.New("secretbox decryption failed")
}
_, _ = c.rxBuf.Write(d)
return c.rxBuf.Read(b)
}
// Write writes data to the connection.
// Write can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
func (c *EncConn) Write(b []byte) (n int, err error) {
c.incNonce(&c.txN, c.txNonce[:])
encBuf := box.SealAfterPrecomputation(nil, b, &c.txNonce, &c.sharedSecret)
if wn, err := c.Conn.Write(encBuf); err != nil {
return wn, err
}
return len(b), nil
}
// initNonce generates the initial nonce
func (c *EncConn) initNonce(buf []byte, xorBy byte) {
for i := 0; i < len(buf)-4; i++ {
buf[i] = c.sharedSecret[i] ^ xorBy
}
}
// incNonce increments a nonce
func (c *EncConn) incNonce(counter *int, buf []byte) {
v := *counter
v++
*counter = v
binary.LittleEndian.PutUint32(buf[len(buf)-5:], uint32(v))
}