Skip to content

Commit

Permalink
Merge branch 'master' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
riobard committed Feb 12, 2017
2 parents af24177 + 3e9aaf3 commit 2db2724
Show file tree
Hide file tree
Showing 17 changed files with 439 additions and 322 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ GoDoc at https://godoc.org/github.com/shadowsocks/go-shadowsocks2/
## Install

```sh
go get github.com/shadowsocks/go-shadowsocks2
go get -u -v github.com/riobard/go-shadowsocks2
```


Expand Down
123 changes: 0 additions & 123 deletions cipher.go

This file was deleted.

29 changes: 0 additions & 29 deletions cipher/aead.go

This file was deleted.

10 changes: 0 additions & 10 deletions cipher/doc.go

This file was deleted.

134 changes: 134 additions & 0 deletions core/cipher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package core

import (
"crypto/md5"
"errors"
"net"
"sort"
"strings"

"github.com/riobard/go-shadowsocks2/shadowaead"
"github.com/riobard/go-shadowsocks2/shadowstream"
)

type Cipher interface {
StreamConnCipher
PacketConnCipher
}

type StreamConnCipher interface {
StreamConn(net.Conn) net.Conn
}

type PacketConnCipher interface {
PacketConn(net.PacketConn) net.PacketConn
}

// ErrCipherNotSupported occurs when a cipher is not supported (likely because of security concerns).
var ErrCipherNotSupported = errors.New("cipher not supported")

// List of AEAD ciphers: key size in bytes and constructor
var aeadList = map[string]struct {
KeySize int
New func([]byte) (shadowaead.Cipher, error)
}{
"aes-128-gcm": {16, shadowaead.AESGCM},
"aes-192-gcm": {24, shadowaead.AESGCM},
"aes-256-gcm": {32, shadowaead.AESGCM},
"chacha20-ietf-poly1305": {32, shadowaead.Chacha20IETFPoly1305},
}

// List of stream ciphers: key size in bytes and constructor
var streamList = map[string]struct {
KeySize int
New func(key []byte) (shadowstream.Cipher, error)
}{
"aes-128-ctr": {16, shadowstream.AESCTR},
"aes-192-ctr": {24, shadowstream.AESCTR},
"aes-256-ctr": {32, shadowstream.AESCTR},
"aes-128-cfb": {16, shadowstream.AESCFB},
"aes-192-cfb": {24, shadowstream.AESCFB},
"aes-256-cfb": {32, shadowstream.AESCFB},
"chacha20-ietf": {32, shadowstream.Chacha20IETF},
}

// ListCipher returns a list of available cipher names sorted alphabetically.
func ListCipher() []string {
var l []string
for k := range aeadList {
l = append(l, k)
}
for k := range streamList {
l = append(l, k)
}
sort.Strings(l)
return l
}

// PickCipher returns a Cipher of the given name. Derive key from password if given key is empty.
func PickCipher(name string, key []byte, password string) (Cipher, error) {
name = strings.ToLower(name)

if name == "dummy" {
return &dummy{}, nil
}

if choice, ok := aeadList[name]; ok {
if len(key) == 0 {
key = kdf(password, choice.KeySize)
}
if len(key) != choice.KeySize {
return nil, shadowaead.KeySizeError(choice.KeySize)
}
aead, err := choice.New(key)
return &aeadCipher{aead}, err
}

if choice, ok := streamList[name]; ok {
if len(key) == 0 {
key = kdf(password, choice.KeySize)
}
if len(key) != choice.KeySize {
return nil, shadowstream.KeySizeError(choice.KeySize)
}
ciph, err := choice.New(key)
return &streamCipher{ciph}, err
}

return nil, ErrCipherNotSupported
}

type aeadCipher struct{ shadowaead.Cipher }

func (aead *aeadCipher) StreamConn(c net.Conn) net.Conn { return shadowaead.NewConn(c, aead) }
func (aead *aeadCipher) PacketConn(c net.PacketConn) net.PacketConn {
return shadowaead.NewPacketConn(c, aead)
}

type streamCipher struct{ shadowstream.Cipher }

func (ciph *streamCipher) StreamConn(c net.Conn) net.Conn { return shadowstream.NewConn(c, ciph) }
func (ciph *streamCipher) PacketConn(c net.PacketConn) net.PacketConn {
return shadowstream.NewPacketConn(c, ciph)
}

// dummy cipher does not encrypt

type dummy struct{}

func (dummy) StreamConn(c net.Conn) net.Conn { return c }
func (dummy) PacketConn(c net.PacketConn) net.PacketConn { return c }

// key-derivation function from original Shadowsocks
func kdf(password string, keyLen int) []byte {
var b, prev []byte
h := md5.New()
for len(b) < keyLen {
h.Write(prev)
h.Write([]byte(password))
b = h.Sum(b)
prev = b[len(b)-h.Size():]
h.Reset()
}
return b[:keyLen]
}
2 changes: 1 addition & 1 deletion core/doc.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Package core provides essential interfaces for Shadowsocks
// Package core implements essential parts of Shadowsocks
package core
4 changes: 1 addition & 3 deletions core/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package core

import "net"

type PacketConnCipher func(net.PacketConn) net.PacketConn

func ListenPacket(network, address string, ciph PacketConnCipher) (net.PacketConn, error) {
c, err := net.ListenPacket(network, address)
return ciph(c), err
return ciph.PacketConn(c), err
}
6 changes: 2 additions & 4 deletions core/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package core

import "net"

type StreamConnCipher func(net.Conn) net.Conn

type listener struct {
net.Listener
StreamConnCipher
Expand All @@ -16,10 +14,10 @@ func Listen(network, address string, ciph StreamConnCipher) (net.Listener, error

func (l *listener) Accept() (net.Conn, error) {
c, err := l.Listener.Accept()
return l.StreamConnCipher(c), err
return l.StreamConn(c), err
}

func Dial(network, address string, ciph StreamConnCipher) (net.Conn, error) {
c, err := net.Dial(network, address)
return ciph(c), err
return ciph.StreamConn(c), err
}
Loading

0 comments on commit 2db2724

Please sign in to comment.