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:
		| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user