From 31f0060b30a2129744f12ceb7ed8dafe3b1fd742 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sat, 21 Jun 2025 10:28:23 +0800 Subject: [PATCH] fix: chacha20 counter overflow the implement it's a not safe chacha20 using but for compatible --- go.mod | 6 +- go.sum | 16 ++++-- .../shadowsocks/shadowstream/chacha20.go | 55 +++++++++++++++++++ transport/shadowsocks/shadowstream/cipher.go | 41 -------------- .../shadowsocks/shadowstream/old_chacha20.go | 23 -------- 5 files changed, 68 insertions(+), 73 deletions(-) create mode 100644 transport/shadowsocks/shadowstream/chacha20.go delete mode 100644 transport/shadowsocks/shadowstream/old_chacha20.go diff --git a/go.mod b/go.mod index d1da5c36..b79db25a 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab github.com/metacubex/bart v0.20.5 github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 - github.com/metacubex/chacha v0.1.2 + github.com/metacubex/chacha v0.1.5 github.com/metacubex/fswatch v0.1.1 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 github.com/metacubex/quic-go v0.52.1-0.20250522021943-aef454b9e639 @@ -28,8 +28,8 @@ require ( github.com/metacubex/sing v0.5.4-0.20250605054047-54dc6097da29 github.com/metacubex/sing-mux v0.3.2 github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f - github.com/metacubex/sing-shadowsocks v0.2.11-0.20250531133822-e545de386d4c - github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250531133559-f4d53bd59335 + github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621023810-0e9ef9dd0c92 + github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621023950-93d605a2143d github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 github.com/metacubex/sing-tun v0.4.7-0.20250611091011-60774779fdd8 github.com/metacubex/sing-vmess v0.2.2 diff --git a/go.sum b/go.sum index 9c0c63d5..71bbbd2b 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,8 @@ github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI= github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 h1:oBowHVKZycNtAFbZ6avaCSZJYeme2Nrj+4RpV2cNJig= github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399/go.mod h1:4xcieuIK+M4bGQmQYZVqEaIYqjS1ahO4kXG7EmDgEro= -github.com/metacubex/chacha v0.1.2 h1:QulCq3eVm3TO6+4nVIWJtmSe7BT2GMrgVHuAoqRQnlc= -github.com/metacubex/chacha v0.1.2/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= +github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M= +github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU= github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= @@ -122,10 +122,14 @@ github.com/metacubex/sing-mux v0.3.2 h1:nJv52pyRivHcaZJKk2JgxpaVvj1GAXG81scSa9N7 github.com/metacubex/sing-mux v0.3.2/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f h1:mP3vIm+9hRFI0C0Vl3pE0NESF/L85FDbuB0tGgUii6I= github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f/go.mod h1:JPTpf7fpnojsSuwRJExhSZSy63pVbp3VM39+zj+sAJM= -github.com/metacubex/sing-shadowsocks v0.2.11-0.20250531133822-e545de386d4c h1:ZfgQx24XIN807046dp9CVBjAh0t9NJIzXG3X5jk+PEM= -github.com/metacubex/sing-shadowsocks v0.2.11-0.20250531133822-e545de386d4c/go.mod h1:MtRM0ZZjR0kaDOzy9zWSt6/4/UlrnsNBq+1FNAF4vBk= -github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250531133559-f4d53bd59335 h1:nSSdMV+I7Tjcb7s6FzNDMj7jH/ZdryY1DHPlgtFjW98= -github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250531133559-f4d53bd59335/go.mod h1:WP8+S0kqtnSbX1vlIpo5i8Irm/ijZITEPBcZ26B5unY= +github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621021503-4f85ef9bf4b3 h1:dtiRj7WaCAXp4UhCkmaIiFF6v886qXiuqeIDN4Z//9E= +github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621021503-4f85ef9bf4b3/go.mod h1:/squZ38pXrYjqtg8qn+joVvwbpGNYQNp8yxKsMVbCto= +github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621023810-0e9ef9dd0c92 h1:Y9ebcKya6ow7VHoESCN5+l4zZvg5eaL2IhI5LLCQxQA= +github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621023810-0e9ef9dd0c92/go.mod h1:/squZ38pXrYjqtg8qn+joVvwbpGNYQNp8yxKsMVbCto= +github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621021638-dcd503063651 h1:vwLj0DDjPYy4AHEZvfRVf8ih52o6wpBnJxXxqa+ztmE= +github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621021638-dcd503063651/go.mod h1:+ukTd0OPFglT3bnKAYTJWYPbuox6HYNXE235r5tHdUk= +github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621023950-93d605a2143d h1:Ey3A1tA8lVkRbK1FDmwuWj/57Nr8JMdpoVqe45mFzJg= +github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621023950-93d605a2143d/go.mod h1:+ukTd0OPFglT3bnKAYTJWYPbuox6HYNXE235r5tHdUk= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= github.com/metacubex/sing-tun v0.4.7-0.20250611091011-60774779fdd8 h1:4zWKqxTx75TbfW2EmlQ3hxM6RTRg2PYOAVMCnU4I61I= diff --git a/transport/shadowsocks/shadowstream/chacha20.go b/transport/shadowsocks/shadowstream/chacha20.go new file mode 100644 index 00000000..c3378e91 --- /dev/null +++ b/transport/shadowsocks/shadowstream/chacha20.go @@ -0,0 +1,55 @@ +package shadowstream + +import ( + "crypto/cipher" + + "github.com/metacubex/chacha" +) + +func newChaCha20(nonce, key []byte) cipher.Stream { + c, err := chacha.NewChaCha20IgnoreCounterOverflow(nonce, key) + if err != nil { + panic(err) // should never happen + } + return c +} + +type chacha20key []byte + +func (k chacha20key) IVSize() int { return chacha.NonceSize } +func (k chacha20key) Encrypter(iv []byte) cipher.Stream { return newChaCha20(iv, k) } +func (k chacha20key) Decrypter(iv []byte) cipher.Stream { return k.Encrypter(iv) } + +func ChaCha20(key []byte) (Cipher, error) { + if len(key) != chacha.KeySize { + return nil, KeySizeError(chacha.KeySize) + } + return chacha20key(key), nil +} + +// IETF-variant of chacha20 +type chacha20ietfkey []byte + +func (k chacha20ietfkey) IVSize() int { return chacha.INonceSize } +func (k chacha20ietfkey) Decrypter(iv []byte) cipher.Stream { return k.Encrypter(iv) } +func (k chacha20ietfkey) Encrypter(iv []byte) cipher.Stream { return newChaCha20(iv, k) } + +func Chacha20IETF(key []byte) (Cipher, error) { + if len(key) != chacha.KeySize { + return nil, KeySizeError(chacha.KeySize) + } + return chacha20ietfkey(key), nil +} + +type xchacha20key []byte + +func (k xchacha20key) IVSize() int { return chacha.XNonceSize } +func (k xchacha20key) Decrypter(iv []byte) cipher.Stream { return k.Encrypter(iv) } +func (k xchacha20key) Encrypter(iv []byte) cipher.Stream { return newChaCha20(iv, k) } + +func Xchacha20(key []byte) (Cipher, error) { + if len(key) != chacha.KeySize { + return nil, KeySizeError(chacha.KeySize) + } + return xchacha20key(key), nil +} diff --git a/transport/shadowsocks/shadowstream/cipher.go b/transport/shadowsocks/shadowstream/cipher.go index dd39d03b..6f916777 100644 --- a/transport/shadowsocks/shadowstream/cipher.go +++ b/transport/shadowsocks/shadowstream/cipher.go @@ -6,8 +6,6 @@ import ( "crypto/md5" "crypto/rc4" "strconv" - - "golang.org/x/crypto/chacha20" ) // Cipher generates a pair of stream ciphers for encryption and decryption. @@ -53,45 +51,6 @@ func AESCFB(key []byte) (Cipher, error) { return &cfbStream{blk}, nil } -// IETF-variant of chacha20 -type chacha20ietfkey []byte - -func (k chacha20ietfkey) IVSize() int { return chacha20.NonceSize } -func (k chacha20ietfkey) Decrypter(iv []byte) cipher.Stream { return k.Encrypter(iv) } -func (k chacha20ietfkey) Encrypter(iv []byte) cipher.Stream { - ciph, err := chacha20.NewUnauthenticatedCipher(k, iv) - if err != nil { - panic(err) // should never happen - } - return ciph -} - -func Chacha20IETF(key []byte) (Cipher, error) { - if len(key) != chacha20.KeySize { - return nil, KeySizeError(chacha20.KeySize) - } - return chacha20ietfkey(key), nil -} - -type xchacha20key []byte - -func (k xchacha20key) IVSize() int { return chacha20.NonceSizeX } -func (k xchacha20key) Decrypter(iv []byte) cipher.Stream { return k.Encrypter(iv) } -func (k xchacha20key) Encrypter(iv []byte) cipher.Stream { - ciph, err := chacha20.NewUnauthenticatedCipher(k, iv) - if err != nil { - panic(err) // should never happen - } - return ciph -} - -func Xchacha20(key []byte) (Cipher, error) { - if len(key) != chacha20.KeySize { - return nil, KeySizeError(chacha20.KeySize) - } - return xchacha20key(key), nil -} - type rc4Md5Key []byte func (k rc4Md5Key) IVSize() int { diff --git a/transport/shadowsocks/shadowstream/old_chacha20.go b/transport/shadowsocks/shadowstream/old_chacha20.go deleted file mode 100644 index eb61232e..00000000 --- a/transport/shadowsocks/shadowstream/old_chacha20.go +++ /dev/null @@ -1,23 +0,0 @@ -package shadowstream - -import ( - "crypto/cipher" - - "github.com/metacubex/chacha" -) - -type chacha20key []byte - -func (k chacha20key) IVSize() int { - return chacha.NonceSize -} -func (k chacha20key) Encrypter(iv []byte) cipher.Stream { - c, _ := chacha.NewChaCha20(iv, k) - return c -} -func (k chacha20key) Decrypter(iv []byte) cipher.Stream { - return k.Encrypter(iv) -} -func ChaCha20(key []byte) (Cipher, error) { - return chacha20key(key), nil -}