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:
parent
b344171c80
commit
43b0dbb123
@ -14,22 +14,17 @@ var (
|
|||||||
// gcmStandardNonceSize from crypto/cipher/gcm.go is 12 bytes
|
// gcmStandardNonceSize from crypto/cipher/gcm.go is 12 bytes
|
||||||
// 100 - is max size of pool
|
// 100 - is max size of pool
|
||||||
noncePool = bpool.NewBytePool(100, 12)
|
noncePool = bpool.NewBytePool(100, 12)
|
||||||
hashPool = bpool.NewBytePool(1024*32, 32)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// hash hahes the data into 32 bytes key and returns it
|
// hash hahes the data into 32 bytes key and returns it
|
||||||
// hash uses sha256 underneath to hash the supplied key
|
// hash uses sha256 underneath to hash the supplied key
|
||||||
func hash(key string) []byte {
|
func hash(key []byte) []byte {
|
||||||
hasher := sha256.New()
|
sum := sha256.Sum256(key)
|
||||||
hasher.Write([]byte(key))
|
return sum[:]
|
||||||
out := hashPool.Get()
|
|
||||||
defer hashPool.Put(out[:0])
|
|
||||||
out = hasher.Sum(out[:0])
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt encrypts data and returns the encrypted data
|
// 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
|
// generate a new AES cipher using our 32 byte key
|
||||||
c, err := aes.NewCipher(hash(key))
|
c, err := aes.NewCipher(hash(key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,7 +54,7 @@ func Encrypt(data []byte, key string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt decrypts the payload and returns the decrypted data
|
// 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
|
// generate AES cipher for decrypting the message
|
||||||
c, err := aes.NewCipher(hash(key))
|
c, err := aes.NewCipher(hash(key))
|
||||||
if err != nil {
|
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
|
// NOTE: we need to parse out nonce from the payload
|
||||||
// we prepend the nonce to every encrypted payload
|
// we prepend the nonce to every encrypted payload
|
||||||
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return plaintext, nil
|
return ciphertext, nil
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestEncrypt(t *testing.T) {
|
func TestEncrypt(t *testing.T) {
|
||||||
key := "tokenpassphrase"
|
key := []byte("tokenpassphrase")
|
||||||
data := []byte("supersecret")
|
data := []byte("supersecret")
|
||||||
|
|
||||||
cipherText, err := Encrypt(data, key)
|
cipherText, err := Encrypt(data, key)
|
||||||
@ -21,7 +21,7 @@ func TestEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDecrypt(t *testing.T) {
|
func TestDecrypt(t *testing.T) {
|
||||||
key := "tokenpassphrase"
|
key := []byte("tokenpassphrase")
|
||||||
data := []byte("supersecret")
|
data := []byte("supersecret")
|
||||||
|
|
||||||
cipherText, err := Encrypt(data, key)
|
cipherText, err := Encrypt(data, key)
|
||||||
|
@ -131,7 +131,7 @@ func (t *tun) newSession(channel, sessionId string) (*session, bool) {
|
|||||||
recv: make(chan *message, 128),
|
recv: make(chan *message, 128),
|
||||||
send: t.send,
|
send: t.send,
|
||||||
errChan: make(chan error, 1),
|
errChan: make(chan error, 1),
|
||||||
key: t.token + channel + sessionId,
|
key: []byte(t.token + channel + sessionId),
|
||||||
}
|
}
|
||||||
|
|
||||||
// save session
|
// save session
|
||||||
|
@ -78,7 +78,7 @@ func (t *tunListener) process() {
|
|||||||
// create a new session session
|
// create a new session session
|
||||||
sess = &session{
|
sess = &session{
|
||||||
// the session key
|
// the session key
|
||||||
key: t.token + m.channel + sessionId,
|
key: []byte(t.token + m.channel + sessionId),
|
||||||
// the id of the remote side
|
// the id of the remote side
|
||||||
tunnel: m.tunnel,
|
tunnel: m.tunnel,
|
||||||
// the channel
|
// the channel
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package tunnel
|
package tunnel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/base32"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ type session struct {
|
|||||||
// the error response
|
// the error response
|
||||||
errChan chan error
|
errChan chan error
|
||||||
// key for session encryption
|
// key for session encryption
|
||||||
key string
|
key []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// message is sent over the send channel
|
// 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)
|
log.Debugf("failed to encrypt message header %s: %v", k, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// hex encode the encrypted header value
|
// add the encrypted header value
|
||||||
data.Header[k] = hex.EncodeToString(val)
|
data.Header[k] = base32.StdEncoding.EncodeToString(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new message
|
// create a new message
|
||||||
@ -391,33 +391,33 @@ func (s *session) Recv(m *transport.Message) error {
|
|||||||
|
|
||||||
log.Tracef("Received %+v from recv backlog", msg)
|
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
|
// decrypt the received payload using the token
|
||||||
// we have to used msg.session because multicast has a shared
|
// we have to used msg.session because multicast has a shared
|
||||||
// session id of "multicast" in this session struct on
|
// session id of "multicast" in this session struct on
|
||||||
// the listener side
|
// the listener side
|
||||||
body, err := Decrypt(msg.data.Body, key)
|
msg.data.Body, err = Decrypt(msg.data.Body, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to decrypt message body: %v", err)
|
log.Debugf("failed to decrypt message body: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msg.data.Body = body
|
|
||||||
|
|
||||||
// encrypt all the headers
|
// dencrypt all the headers
|
||||||
for k, v := range msg.data.Header {
|
for k, v := range msg.data.Header {
|
||||||
// hex decode the header values
|
// decode the header values
|
||||||
h, err := hex.DecodeString(v)
|
h, err := base32.StdEncoding.DecodeString(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to decode message header %s: %v", k, err)
|
log.Debugf("failed to decode message header %s: %v", k, err)
|
||||||
return 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 {
|
if err != nil {
|
||||||
log.Debugf("failed to decrypt message header %s: %v", k, err)
|
log.Debugf("failed to decrypt message header %s: %v", k, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// hex encode the encrypted header value
|
// add decrypted header value
|
||||||
msg.data.Header[k] = string(val)
|
msg.data.Header[k] = string(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user