2019-08-02 19:50:08 +00:00
|
|
|
package multiplex
|
|
|
|
|
|
|
|
import (
|
2019-08-03 21:05:06 +00:00
|
|
|
"crypto/aes"
|
|
|
|
"crypto/cipher"
|
2020-12-28 12:04:32 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2019-08-03 21:05:06 +00:00
|
|
|
"golang.org/x/crypto/chacha20poly1305"
|
2019-08-02 19:50:08 +00:00
|
|
|
"math/rand"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"testing/quick"
|
|
|
|
)
|
|
|
|
|
2019-08-06 23:15:12 +00:00
|
|
|
func TestGenerateObfs(t *testing.T) {
|
2020-04-07 20:19:40 +00:00
|
|
|
var sessionKey [32]byte
|
|
|
|
rand.Read(sessionKey[:])
|
2019-08-02 19:50:08 +00:00
|
|
|
|
2020-12-28 12:04:32 +00:00
|
|
|
run := func(o Obfuscator, t *testing.T) {
|
2019-08-04 09:38:49 +00:00
|
|
|
obfsBuf := make([]byte, 512)
|
2020-12-28 12:15:01 +00:00
|
|
|
_testFrame, _ := quick.Value(reflect.TypeOf(Frame{}), rand.New(rand.NewSource(42)))
|
|
|
|
testFrame := _testFrame.Interface().(Frame)
|
|
|
|
i, err := o.obfuscate(&testFrame, obfsBuf, 0)
|
2020-12-28 12:04:32 +00:00
|
|
|
assert.NoError(t, err)
|
2020-12-22 14:45:29 +00:00
|
|
|
var resultFrame Frame
|
2020-12-28 12:04:32 +00:00
|
|
|
|
|
|
|
err = o.deobfuscate(&resultFrame, obfsBuf[:i])
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, testFrame, resultFrame)
|
2019-08-02 19:50:08 +00:00
|
|
|
}
|
2019-08-03 21:05:06 +00:00
|
|
|
|
|
|
|
t.Run("plain", func(t *testing.T) {
|
2020-12-28 12:04:32 +00:00
|
|
|
o, err := MakeObfuscator(EncryptionMethodPlain, sessionKey)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
run(o, t)
|
2019-09-01 19:23:45 +00:00
|
|
|
})
|
2020-12-27 13:26:45 +00:00
|
|
|
t.Run("aes-256-gcm", func(t *testing.T) {
|
2020-12-28 12:04:32 +00:00
|
|
|
o, err := MakeObfuscator(EncryptionMethodAES256GCM, sessionKey)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
run(o, t)
|
2020-12-27 13:26:45 +00:00
|
|
|
})
|
|
|
|
t.Run("aes-128-gcm", func(t *testing.T) {
|
2020-12-28 12:04:32 +00:00
|
|
|
o, err := MakeObfuscator(EncryptionMethodAES128GCM, sessionKey)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
run(o, t)
|
2019-09-01 19:23:45 +00:00
|
|
|
})
|
2019-08-03 21:05:06 +00:00
|
|
|
t.Run("chacha20-poly1305", func(t *testing.T) {
|
2020-12-28 12:04:32 +00:00
|
|
|
o, err := MakeObfuscator(EncryptionMethodChaha20Poly1305, sessionKey)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
run(o, t)
|
2019-08-06 23:19:30 +00:00
|
|
|
})
|
|
|
|
t.Run("unknown encryption method", func(t *testing.T) {
|
2020-04-08 20:47:31 +00:00
|
|
|
_, err := MakeObfuscator(0xff, sessionKey)
|
2020-12-28 12:04:32 +00:00
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestObfuscate(t *testing.T) {
|
|
|
|
var sessionKey [32]byte
|
|
|
|
rand.Read(sessionKey[:])
|
|
|
|
|
|
|
|
const testPayloadLen = 1024
|
|
|
|
testPayload := make([]byte, testPayloadLen)
|
|
|
|
rand.Read(testPayload)
|
|
|
|
f := Frame{
|
|
|
|
StreamID: 0,
|
|
|
|
Seq: 0,
|
|
|
|
Closing: 0,
|
|
|
|
Payload: testPayload,
|
|
|
|
}
|
|
|
|
|
|
|
|
runTest := func(t *testing.T, o Obfuscator) {
|
|
|
|
obfsBuf := make([]byte, testPayloadLen*2)
|
|
|
|
n, err := o.obfuscate(&f, obfsBuf, 0)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
resultFrame := Frame{}
|
|
|
|
err = o.deobfuscate(&resultFrame, obfsBuf[:n])
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
assert.EqualValues(t, f, resultFrame)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("plain", func(t *testing.T) {
|
|
|
|
o := Obfuscator{
|
|
|
|
payloadCipher: nil,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: sessionKey,
|
2020-12-28 12:04:32 +00:00
|
|
|
maxOverhead: salsa20NonceSize,
|
2019-08-06 23:19:30 +00:00
|
|
|
}
|
2020-12-28 12:04:32 +00:00
|
|
|
runTest(t, o)
|
2019-08-06 23:19:30 +00:00
|
|
|
})
|
2020-12-28 12:04:32 +00:00
|
|
|
|
|
|
|
t.Run("aes-128-gcm", func(t *testing.T) {
|
|
|
|
c, err := aes.NewCipher(sessionKey[:16])
|
|
|
|
assert.NoError(t, err)
|
|
|
|
payloadCipher, err := cipher.NewGCM(c)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
o := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: sessionKey,
|
2020-12-28 12:04:32 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
|
|
|
runTest(t, o)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("aes-256-gcm", func(t *testing.T) {
|
|
|
|
c, err := aes.NewCipher(sessionKey[:])
|
|
|
|
assert.NoError(t, err)
|
|
|
|
payloadCipher, err := cipher.NewGCM(c)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
o := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: sessionKey,
|
2020-12-28 12:04:32 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
|
|
|
runTest(t, o)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("chacha20-poly1305", func(t *testing.T) {
|
|
|
|
payloadCipher, err := chacha20poly1305.New(sessionKey[:])
|
|
|
|
assert.NoError(t, err)
|
|
|
|
o := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: sessionKey,
|
2020-12-28 12:04:32 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
|
|
|
runTest(t, o)
|
|
|
|
})
|
|
|
|
|
2019-08-03 21:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkObfs(b *testing.B) {
|
|
|
|
testPayload := make([]byte, 1024)
|
|
|
|
rand.Read(testPayload)
|
|
|
|
testFrame := &Frame{
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
testPayload,
|
2019-08-02 19:50:08 +00:00
|
|
|
}
|
|
|
|
|
2020-04-13 18:40:23 +00:00
|
|
|
obfsBuf := make([]byte, defaultSendRecvBufSize)
|
2019-08-04 09:38:49 +00:00
|
|
|
|
2019-08-03 21:05:06 +00:00
|
|
|
var key [32]byte
|
|
|
|
rand.Read(key[:])
|
|
|
|
b.Run("AES256GCM", func(b *testing.B) {
|
|
|
|
c, _ := aes.NewCipher(key[:])
|
|
|
|
payloadCipher, _ := cipher.NewGCM(c)
|
|
|
|
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
|
|
|
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(len(testFrame.Payload)))
|
2019-08-03 21:05:06 +00:00
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-03 21:05:06 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
b.Run("AES128GCM", func(b *testing.B) {
|
|
|
|
c, _ := aes.NewCipher(key[:16])
|
|
|
|
payloadCipher, _ := cipher.NewGCM(c)
|
|
|
|
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(len(testFrame.Payload)))
|
2019-08-03 21:05:06 +00:00
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-03 21:05:06 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
b.Run("plain", func(b *testing.B) {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: nil,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: salsa20NonceSize,
|
|
|
|
}
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(len(testFrame.Payload)))
|
2019-08-03 21:05:06 +00:00
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-03 21:05:06 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
b.Run("chacha20Poly1305", func(b *testing.B) {
|
2020-12-26 00:49:36 +00:00
|
|
|
payloadCipher, _ := chacha20poly1305.New(key[:])
|
2019-08-03 21:05:06 +00:00
|
|
|
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(len(testFrame.Payload)))
|
2019-08-03 21:05:06 +00:00
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-07 16:06:31 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkDeobfs(b *testing.B) {
|
|
|
|
testPayload := make([]byte, 1024)
|
|
|
|
rand.Read(testPayload)
|
|
|
|
testFrame := &Frame{
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
testPayload,
|
|
|
|
}
|
|
|
|
|
2020-04-13 18:40:23 +00:00
|
|
|
obfsBuf := make([]byte, defaultSendRecvBufSize)
|
2019-08-07 16:06:31 +00:00
|
|
|
|
|
|
|
var key [32]byte
|
|
|
|
rand.Read(key[:])
|
|
|
|
b.Run("AES256GCM", func(b *testing.B) {
|
|
|
|
c, _ := aes.NewCipher(key[:])
|
|
|
|
payloadCipher, _ := cipher.NewGCM(c)
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
2019-08-07 16:06:31 +00:00
|
|
|
|
2020-12-26 00:49:36 +00:00
|
|
|
n, _ := obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-07 16:06:31 +00:00
|
|
|
|
2020-12-22 14:45:29 +00:00
|
|
|
frame := new(Frame)
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(n))
|
2019-08-07 16:06:31 +00:00
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.deobfuscate(frame, obfsBuf[:n])
|
2019-08-07 16:06:31 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
b.Run("AES128GCM", func(b *testing.B) {
|
|
|
|
c, _ := aes.NewCipher(key[:16])
|
|
|
|
payloadCipher, _ := cipher.NewGCM(c)
|
|
|
|
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: payloadCipher,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
|
|
|
n, _ := obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-07 16:06:31 +00:00
|
|
|
|
2020-12-22 14:45:29 +00:00
|
|
|
frame := new(Frame)
|
2019-08-07 16:06:31 +00:00
|
|
|
b.ResetTimer()
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(n))
|
2019-08-07 16:06:31 +00:00
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.deobfuscate(frame, obfsBuf[:n])
|
2019-08-07 16:06:31 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
b.Run("plain", func(b *testing.B) {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: nil,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: salsa20NonceSize,
|
|
|
|
}
|
|
|
|
n, _ := obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-07 16:06:31 +00:00
|
|
|
|
2020-12-22 14:45:29 +00:00
|
|
|
frame := new(Frame)
|
2019-08-07 16:06:31 +00:00
|
|
|
b.ResetTimer()
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(n))
|
2019-08-07 16:06:31 +00:00
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.deobfuscate(frame, obfsBuf[:n])
|
2019-08-07 16:06:31 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
b.Run("chacha20Poly1305", func(b *testing.B) {
|
2020-12-26 00:49:36 +00:00
|
|
|
payloadCipher, _ := chacha20poly1305.New(key[:])
|
|
|
|
|
|
|
|
obfuscator := Obfuscator{
|
|
|
|
payloadCipher: nil,
|
2020-12-28 12:15:01 +00:00
|
|
|
sessionKey: key,
|
2020-12-26 00:49:36 +00:00
|
|
|
maxOverhead: payloadCipher.Overhead(),
|
|
|
|
}
|
2019-08-07 16:06:31 +00:00
|
|
|
|
2020-12-26 00:49:36 +00:00
|
|
|
n, _ := obfuscator.obfuscate(testFrame, obfsBuf, 0)
|
2019-08-07 16:06:31 +00:00
|
|
|
|
2020-12-22 14:45:29 +00:00
|
|
|
frame := new(Frame)
|
2019-08-07 16:06:31 +00:00
|
|
|
b.ResetTimer()
|
2020-04-13 18:40:23 +00:00
|
|
|
b.SetBytes(int64(n))
|
2019-08-07 16:06:31 +00:00
|
|
|
for i := 0; i < b.N; i++ {
|
2020-12-26 00:49:36 +00:00
|
|
|
obfuscator.deobfuscate(frame, obfsBuf[:n])
|
2019-08-03 21:05:06 +00:00
|
|
|
}
|
|
|
|
})
|
2019-08-02 19:50:08 +00:00
|
|
|
}
|