From f37132612c3f61106a858147046be47300e735b5 Mon Sep 17 00:00:00 2001 From: Barry Deng Date: Mon, 26 Feb 2024 17:54:49 +0800 Subject: [PATCH] fix core --- core/cipher.go | 79 ++++++++++++++++++++++++++++++++++++++++++-------- core/packet.go | 8 ----- core/stream.go | 23 --------------- 3 files changed, 67 insertions(+), 43 deletions(-) delete mode 100644 core/packet.go delete mode 100644 core/stream.go diff --git a/core/cipher.go b/core/cipher.go index baed0078..16f85277 100644 --- a/core/cipher.go +++ b/core/cipher.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/BarryDeng/go-shadowsocks2/shadowaead" + "github.com/BarryDeng/go-shadowsocks2/shadowstream" ) type Cipher interface { @@ -27,9 +28,12 @@ type PacketConnCipher interface { var ErrCipherNotSupported = errors.New("cipher not supported") const ( - aeadAes128Gcm = "AEAD_AES_128_GCM" - aeadAes256Gcm = "AEAD_AES_256_GCM" - aeadChacha20Poly1305 = "AEAD_CHACHA20_POLY1305" + aeadAes128Gcm = "AEAD_AES_128_GCM" + aeadAes192Gcm = "AEAD_AES_192_GCM" + aeadAes256Gcm = "AEAD_AES_256_GCM" + aeadChacha20Poly1305 = "AEAD_CHACHA20_POLY1305" + aeadXChacha20Poly1305 = "AEAD_XCHACHA20_POLY1305" + sm4128Gcm = "SM4_128_GCM" ) // List of AEAD ciphers: key size in bytes and constructor @@ -37,9 +41,28 @@ var aeadList = map[string]struct { KeySize int New func([]byte) (shadowaead.Cipher, error) }{ - aeadAes128Gcm: {16, shadowaead.AESGCM}, - aeadAes256Gcm: {32, shadowaead.AESGCM}, - aeadChacha20Poly1305: {32, shadowaead.Chacha20Poly1305}, + aeadAes128Gcm: {16, shadowaead.AESGCM}, + aeadAes192Gcm: {24, shadowaead.AESGCM}, + aeadAes256Gcm: {32, shadowaead.AESGCM}, + aeadChacha20Poly1305: {32, shadowaead.Chacha20Poly1305}, + aeadXChacha20Poly1305: {32, shadowaead.XChacha20Poly1305}, + sm4128Gcm: {16, shadowaead.SM4GCM}, +} + +// List of stream ciphers: key size in bytes and constructor +var streamList = map[string]struct { + KeySize int + New func(key []byte) (shadowstream.Cipher, error) +}{ + "RC4-MD5": {16, shadowstream.RC4MD5}, + "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}, + "XCHACHA20": {32, shadowstream.Xchacha20}, } // ListCipher returns a list of available cipher names sorted alphabetically. @@ -61,33 +84,65 @@ func PickCipher(name string, key []byte, password string) (Cipher, error) { return &dummy{}, nil case "CHACHA20-IETF-POLY1305": name = aeadChacha20Poly1305 + case "XCHACHA20-IETF-POLY1305": + name = aeadXChacha20Poly1305 case "AES-128-GCM": name = aeadAes128Gcm + case "AES-192-GCM": + name = aeadAes192Gcm case "AES-256-GCM": name = aeadAes256Gcm + case "SM4-128-GCM": + name = sm4128Gcm } if choice, ok := aeadList[name]; ok { if len(key) == 0 { - key = kdf(password, choice.KeySize) + 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 + return &AeadCipher{Cipher: aead, Key: key}, 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{Cipher: ciph, Key: key}, err } return nil, ErrCipherNotSupported } -type aeadCipher struct{ shadowaead.Cipher } +type AeadCipher struct { + shadowaead.Cipher + + Key []byte +} -func (aead *aeadCipher) StreamConn(c net.Conn) net.Conn { return shadowaead.NewConn(c, aead) } -func (aead *aeadCipher) PacketConn(c net.PacketConn) net.PacketConn { +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 + + Key []byte +} + +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{} @@ -95,7 +150,7 @@ 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 { +func Kdf(password string, keyLen int) []byte { var b, prev []byte h := md5.New() for len(b) < keyLen { diff --git a/core/packet.go b/core/packet.go deleted file mode 100644 index 641aa134..00000000 --- a/core/packet.go +++ /dev/null @@ -1,8 +0,0 @@ -package core - -import "net" - -func ListenPacket(network, address string, ciph PacketConnCipher) (net.PacketConn, error) { - c, err := net.ListenPacket(network, address) - return ciph.PacketConn(c), err -} diff --git a/core/stream.go b/core/stream.go deleted file mode 100644 index 5c773cd2..00000000 --- a/core/stream.go +++ /dev/null @@ -1,23 +0,0 @@ -package core - -import "net" - -type listener struct { - net.Listener - StreamConnCipher -} - -func Listen(network, address string, ciph StreamConnCipher) (net.Listener, error) { - l, err := net.Listen(network, address) - return &listener{l, ciph}, err -} - -func (l *listener) Accept() (net.Conn, error) { - c, err := l.Listener.Accept() - return l.StreamConn(c), err -} - -func Dial(network, address string, ciph StreamConnCipher) (net.Conn, error) { - c, err := net.Dial(network, address) - return ciph.StreamConn(c), err -}