diff --git a/cmd/ck-client/ck-client.go b/cmd/ck-client/ck-client.go index 9482083..de2873b 100644 --- a/cmd/ck-client/ck-client.go +++ b/cmd/ck-client/ck-client.go @@ -192,6 +192,12 @@ start: log.Println(err) return } + case 0x02: + crypto, err = mux.MakeCPCipher(sta.UID) + if err != nil { + log.Println(err) + return + } } obfs := mux.MakeObfs(sta.UID, crypto) diff --git a/cmd/ck-server/ck-server.go b/cmd/ck-server/ck-server.go index 99df4f5..d8fd044 100644 --- a/cmd/ck-server/ck-server.go +++ b/cmd/ck-server/ck-server.go @@ -160,7 +160,15 @@ func dispatchConnection(conn net.Conn, sta *server.State) { goWeb(data) return } + case 0x02: + crypto, err = mux.MakeCPCipher(UID) + if err != nil { + log.Println(err) + goWeb(data) + return + } default: + log.Println("Unknown encryption method") goWeb(data) return } diff --git a/internal/client/state.go b/internal/client/state.go index f03a807..7797e19 100644 --- a/internal/client/state.go +++ b/internal/client/state.go @@ -112,6 +112,8 @@ func (sta *State) ParseConfig(conf string) (err error) { sta.EncryptionMethod = 0x00 case "aes": sta.EncryptionMethod = 0x01 + case "chacha20-poly1305": + sta.EncryptionMethod = 0x02 default: return errors.New("Unknown encryption method") } diff --git a/internal/multiplex/crypto.go b/internal/multiplex/crypto.go index 67c5f23..ff439db 100644 --- a/internal/multiplex/crypto.go +++ b/internal/multiplex/crypto.go @@ -4,6 +4,7 @@ import ( "crypto/aes" "crypto/cipher" "crypto/rand" + "golang.org/x/crypto/chacha20poly1305" ) type Crypto interface { @@ -60,3 +61,33 @@ func (a *AES) decrypt(ciphertext []byte, nonce []byte) ([]byte, error) { } return plain, nil } + +type C20P1305 struct { + cipher cipher.AEAD +} + +func MakeCPCipher(key []byte) (*C20P1305, error) { + c, err := chacha20poly1305.New(key) + if err != nil { + return nil, err + } + ret := C20P1305{ + c, + } + return &ret, nil +} + +func (c *C20P1305) encrypt(plaintext []byte, nonce []byte) ([]byte, error) { + ciphertext := c.cipher.Seal(nil, nonce, plaintext, nil) + ret := make([]byte, len(plaintext)+16) + copy(ret, ciphertext) + return ret, nil +} + +func (c *C20P1305) decrypt(ciphertext []byte, nonce []byte) ([]byte, error) { + plain, err := c.cipher.Open(nil, nonce, ciphertext, nil) + if err != nil { + return nil, err + } + return plain, nil +} diff --git a/internal/multiplex/obfs.go b/internal/multiplex/obfs.go index 429785e..e8f3f06 100644 --- a/internal/multiplex/obfs.go +++ b/internal/multiplex/obfs.go @@ -47,6 +47,7 @@ func MakeObfs(key []byte, algo Crypto) Obfser { // Composing final obfsed message // We don't use util.AddRecordLayer here to avoid unnecessary malloc + // TODO: allocate this in the beginning and do everything in place obfsed := make([]byte, 5+headerLen+len(encryptedPayload)) obfsed[0] = 0x17 obfsed[1] = 0x03