tunnel: reduce allocation and improve performance (#1320)

* tunnel: reduce allocation and improve performance

BenchmarkSha256Old-16 100000 156748 ns/op 11835 B/op 168 allocs/op
BenchmarkSha256Old-16 100000 156229 ns/op 11819 B/op 168 allocs/op

BenchmarkSha256New-16 100000 154751 ns/op 11107 B/op 161 allocs/op
BenchmarkSha256New-16 100000 154263 ns/op 11110 B/op 161 allocs/op

simple change lowers allocations and brings performance

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* tunnel: reuse buf in Decrypt

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix unneeded conversations

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* base32 string is smaller than hex string

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2020-03-09 20:10:08 +03:00 committed by GitHub
parent b344171c80
commit 43b0dbb123
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 29 deletions

View File

@ -14,22 +14,17 @@ var (
// gcmStandardNonceSize from crypto/cipher/gcm.go is 12 bytes
// 100 - is max size of pool
noncePool = bpool.NewBytePool(100, 12)
hashPool = bpool.NewBytePool(1024*32, 32)
)
// hash hahes the data into 32 bytes key and returns it
// hash uses sha256 underneath to hash the supplied key
func hash(key string) []byte {
hasher := sha256.New()
hasher.Write([]byte(key))
out := hashPool.Get()
defer hashPool.Put(out[:0])
out = hasher.Sum(out[:0])
return out
func hash(key []byte) []byte {
sum := sha256.Sum256(key)
return sum[:]
}
// Encrypt encrypts data and returns the encrypted data
func Encrypt(data []byte, key string) ([]byte, error) {
func Encrypt(data []byte, key []byte) ([]byte, error) {
// generate a new AES cipher using our 32 byte key
c, err := aes.NewCipher(hash(key))
if err != nil {
@ -59,7 +54,7 @@ func Encrypt(data []byte, key string) ([]byte, error) {
}
// Decrypt decrypts the payload and returns the decrypted data
func Decrypt(data []byte, key string) ([]byte, error) {
func Decrypt(data []byte, key []byte) ([]byte, error) {
// generate AES cipher for decrypting the message
c, err := aes.NewCipher(hash(key))
if err != nil {
@ -81,10 +76,10 @@ func Decrypt(data []byte, key string) ([]byte, error) {
// NOTE: we need to parse out nonce from the payload
// we prepend the nonce to every encrypted payload
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
ciphertext, err = gcm.Open(ciphertext[:0], nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return plaintext, nil
return ciphertext, nil
}

View File

@ -6,7 +6,7 @@ import (
)
func TestEncrypt(t *testing.T) {
key := "tokenpassphrase"
key := []byte("tokenpassphrase")
data := []byte("supersecret")
cipherText, err := Encrypt(data, key)
@ -21,7 +21,7 @@ func TestEncrypt(t *testing.T) {
}
func TestDecrypt(t *testing.T) {
key := "tokenpassphrase"
key := []byte("tokenpassphrase")
data := []byte("supersecret")
cipherText, err := Encrypt(data, key)

View File

@ -131,7 +131,7 @@ func (t *tun) newSession(channel, sessionId string) (*session, bool) {
recv: make(chan *message, 128),
send: t.send,
errChan: make(chan error, 1),
key: t.token + channel + sessionId,
key: []byte(t.token + channel + sessionId),
}
// save session

View File

@ -78,7 +78,7 @@ func (t *tunListener) process() {
// create a new session session
sess = &session{
// the session key
key: t.token + m.channel + sessionId,
key: []byte(t.token + m.channel + sessionId),
// the id of the remote side
tunnel: m.tunnel,
// the channel

View File

@ -1,7 +1,7 @@
package tunnel
import (
"encoding/hex"
"encoding/base32"
"io"
"time"
@ -48,7 +48,7 @@ type session struct {
// the error response
errChan chan error
// key for session encryption
key string
key []byte
}
// message is sent over the send channel
@ -348,8 +348,8 @@ func (s *session) Send(m *transport.Message) error {
log.Debugf("failed to encrypt message header %s: %v", k, err)
return err
}
// hex encode the encrypted header value
data.Header[k] = hex.EncodeToString(val)
// add the encrypted header value
data.Header[k] = base32.StdEncoding.EncodeToString(val)
}
// create a new message
@ -391,33 +391,33 @@ func (s *session) Recv(m *transport.Message) error {
log.Tracef("Received %+v from recv backlog", msg)
key := s.token + s.channel + msg.session
key := []byte(s.token + s.channel + msg.session)
// decrypt the received payload using the token
// we have to used msg.session because multicast has a shared
// session id of "multicast" in this session struct on
// the listener side
body, err := Decrypt(msg.data.Body, key)
msg.data.Body, err = Decrypt(msg.data.Body, key)
if err != nil {
log.Debugf("failed to decrypt message body: %v", err)
return err
}
msg.data.Body = body
// encrypt all the headers
// dencrypt all the headers
for k, v := range msg.data.Header {
// hex decode the header values
h, err := hex.DecodeString(v)
// decode the header values
h, err := base32.StdEncoding.DecodeString(v)
if err != nil {
log.Debugf("failed to decode message header %s: %v", k, err)
return err
}
// encrypt the transport message payload
val, err := Decrypt([]byte(h), key)
// dencrypt the transport message payload
val, err := Decrypt(h, key)
if err != nil {
log.Debugf("failed to decrypt message header %s: %v", k, err)
return err
}
// hex encode the encrypted header value
// add decrypted header value
msg.data.Header[k] = string(val)
}