Rewrite hap secure connection
This commit is contained in:
+1
-1
@@ -217,7 +217,7 @@ func (c *Client) Dial() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// new reader for new conn
|
// new reader for new conn
|
||||||
c.reader = bufio.NewReaderSize(c.Conn, 32*1024) // 32K like default request body
|
c.reader = bufio.NewReader(c.Conn)
|
||||||
|
|
||||||
go c.eventsReader()
|
go c.eventsReader()
|
||||||
|
|
||||||
|
|||||||
+60
-49
@@ -1,6 +1,7 @@
|
|||||||
package secure
|
package secure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@@ -14,6 +15,10 @@ import (
|
|||||||
type Conn struct {
|
type Conn struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
|
|
||||||
|
rd *bufio.Reader
|
||||||
|
wr *bufio.Writer
|
||||||
|
rb []byte // temporary reading buffer
|
||||||
|
|
||||||
encryptKey []byte
|
encryptKey []byte
|
||||||
decryptKey []byte
|
decryptKey []byte
|
||||||
encryptCnt uint64
|
encryptCnt uint64
|
||||||
@@ -33,11 +38,19 @@ func Client(conn net.Conn, sharedKey []byte, isClient bool) (net.Conn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isClient {
|
c := &Conn{
|
||||||
return &Conn{conn: conn, encryptKey: key2, decryptKey: key1}, nil
|
conn: conn,
|
||||||
} else {
|
rd: bufio.NewReaderSize(conn, BufferSize),
|
||||||
return &Conn{conn: conn, encryptKey: key1, decryptKey: key2}, nil
|
wr: bufio.NewWriterSize(conn, BufferSize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isClient {
|
||||||
|
c.encryptKey, c.decryptKey = key2, key1
|
||||||
|
} else {
|
||||||
|
c.encryptKey, c.decryptKey = key1, key2
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -47,87 +60,85 @@ const (
|
|||||||
VerifySize = 2
|
VerifySize = 2
|
||||||
NonceSize = 8
|
NonceSize = 8
|
||||||
Overhead = 16 // chacha20poly1305.Overhead
|
Overhead = 16 // chacha20poly1305.Overhead
|
||||||
|
|
||||||
|
BufferSize = 2 + 0xFFFF + Overhead
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Conn) Read(b []byte) (n int, err error) {
|
func (c *Conn) Read(b []byte) (n int, err error) {
|
||||||
verify := make([]byte, VerifySize) // = packet length
|
// something in reading buffer
|
||||||
buf := make([]byte, PacketSizeMax+Overhead)
|
if len(c.rb) > 0 {
|
||||||
|
n = copy(b, c.rb)
|
||||||
|
c.rb = c.rb[n:]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
verify := make([]byte, 2) // verify = plain message size
|
||||||
|
if _, err = io.ReadFull(c.rd, verify); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
n = int(binary.LittleEndian.Uint16(verify))
|
||||||
|
ciphertext := make([]byte, n+Overhead)
|
||||||
|
|
||||||
|
if _, err = io.ReadFull(c.rd, ciphertext); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
nonce := make([]byte, NonceSize)
|
nonce := make([]byte, NonceSize)
|
||||||
|
|
||||||
for {
|
|
||||||
if len(b) < PacketSizeMax {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = io.ReadFull(c.conn, verify); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
size := binary.LittleEndian.Uint16(verify)
|
|
||||||
ciphertext := buf[:size+Overhead]
|
|
||||||
|
|
||||||
if _, err = io.ReadFull(c.conn, ciphertext); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
binary.LittleEndian.PutUint64(nonce, c.decryptCnt)
|
binary.LittleEndian.PutUint64(nonce, c.decryptCnt)
|
||||||
c.decryptCnt++
|
c.decryptCnt++
|
||||||
|
|
||||||
// put decrypted text to b's end
|
// buffer size enought for direct reading
|
||||||
|
if n <= cap(b) {
|
||||||
_, err = chacha20poly1305.DecryptAndVerify(c.decryptKey, b[:0], nonce, ciphertext, verify)
|
_, err = chacha20poly1305.DecryptAndVerify(c.decryptKey, b[:0], nonce, ciphertext, verify)
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n += int(size) // plaintext size
|
// reading to temporary buffer
|
||||||
|
c.rb = make([]byte, 0, n)
|
||||||
// Finish when all bytes fit in b
|
if _, err = chacha20poly1305.DecryptAndVerify(c.decryptKey, c.rb, nonce, ciphertext, verify); err != nil {
|
||||||
if size < PacketSizeMax {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
return c.Read(b)
|
||||||
b = b[size:]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Write(b []byte) (n int, err error) {
|
func (c *Conn) Write(b []byte) (n int, err error) {
|
||||||
c.mx.Lock()
|
var ciphertext []byte
|
||||||
defer c.mx.Unlock()
|
var nonce = make([]byte, NonceSize)
|
||||||
|
var verify = make([]byte, VerifySize)
|
||||||
|
|
||||||
nonce := make([]byte, NonceSize)
|
for len(b) > 0 {
|
||||||
buf := make([]byte, NonceSize+PacketSizeMax+Overhead)
|
|
||||||
verify := buf[:VerifySize] // part of write buffer
|
|
||||||
|
|
||||||
for {
|
|
||||||
size := len(b)
|
size := len(b)
|
||||||
if size > PacketSizeMax {
|
if size > PacketSizeMax {
|
||||||
size = PacketSizeMax
|
size = PacketSizeMax
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.LittleEndian.PutUint16(verify, uint16(size))
|
binary.LittleEndian.PutUint16(verify, uint16(size))
|
||||||
|
if _, err = c.wr.Write(verify); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
binary.LittleEndian.PutUint64(nonce, c.encryptCnt)
|
binary.LittleEndian.PutUint64(nonce, c.encryptCnt)
|
||||||
c.encryptCnt++
|
c.encryptCnt++
|
||||||
|
|
||||||
// put encrypted text to writing buffer just after size (2 bytes)
|
if cap(ciphertext) < size+Overhead {
|
||||||
_, err = chacha20poly1305.EncryptAndSeal(c.encryptKey, buf[2:2], nonce, b[:size], verify)
|
ciphertext = make([]byte, size+Overhead)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = chacha20poly1305.EncryptAndSeal(c.encryptKey, ciphertext[:0], nonce, b[:size], verify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = c.conn.Write(buf[:VerifySize+size+Overhead]); err != nil {
|
if _, err = c.wr.Write(ciphertext); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n += size // plaintext size
|
b = b[size:]
|
||||||
|
n += size
|
||||||
if size < PacketSizeMax {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
b = b[PacketSizeMax:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = c.wr.Flush()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user