github.com/v2fly/v2ray-core/v4@v4.45.2/proxy/shadowsocks/config.go (about)

     1  package shadowsocks
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"crypto/md5"
     8  	"crypto/sha1"
     9  	"io"
    10  
    11  	"golang.org/x/crypto/chacha20poly1305"
    12  	"golang.org/x/crypto/hkdf"
    13  
    14  	"github.com/v2fly/v2ray-core/v4/common"
    15  	"github.com/v2fly/v2ray-core/v4/common/antireplay"
    16  	"github.com/v2fly/v2ray-core/v4/common/buf"
    17  	"github.com/v2fly/v2ray-core/v4/common/crypto"
    18  	"github.com/v2fly/v2ray-core/v4/common/protocol"
    19  )
    20  
    21  // MemoryAccount is an account type converted from Account.
    22  type MemoryAccount struct {
    23  	Cipher Cipher
    24  	Key    []byte
    25  
    26  	replayFilter antireplay.GeneralizedReplayFilter
    27  }
    28  
    29  // Equals implements protocol.Account.Equals().
    30  func (a *MemoryAccount) Equals(another protocol.Account) bool {
    31  	if account, ok := another.(*MemoryAccount); ok {
    32  		return bytes.Equal(a.Key, account.Key)
    33  	}
    34  	return false
    35  }
    36  
    37  func (a *MemoryAccount) CheckIV(iv []byte) error {
    38  	if a.replayFilter == nil {
    39  		return nil
    40  	}
    41  	if a.replayFilter.Check(iv) {
    42  		return nil
    43  	}
    44  	return newError("IV is not unique")
    45  }
    46  
    47  func createAesGcm(key []byte) cipher.AEAD {
    48  	block, err := aes.NewCipher(key)
    49  	common.Must(err)
    50  	gcm, err := cipher.NewGCM(block)
    51  	common.Must(err)
    52  	return gcm
    53  }
    54  
    55  func createChaCha20Poly1305(key []byte) cipher.AEAD {
    56  	ChaChaPoly1305, err := chacha20poly1305.New(key)
    57  	common.Must(err)
    58  	return ChaChaPoly1305
    59  }
    60  
    61  func (a *Account) getCipher() (Cipher, error) {
    62  	switch a.CipherType {
    63  	case CipherType_AES_128_GCM:
    64  		return &AEADCipher{
    65  			KeyBytes:        16,
    66  			IVBytes:         16,
    67  			AEADAuthCreator: createAesGcm,
    68  		}, nil
    69  	case CipherType_AES_256_GCM:
    70  		return &AEADCipher{
    71  			KeyBytes:        32,
    72  			IVBytes:         32,
    73  			AEADAuthCreator: createAesGcm,
    74  		}, nil
    75  	case CipherType_CHACHA20_POLY1305:
    76  		return &AEADCipher{
    77  			KeyBytes:        32,
    78  			IVBytes:         32,
    79  			AEADAuthCreator: createChaCha20Poly1305,
    80  		}, nil
    81  	case CipherType_NONE:
    82  		return NoneCipher{}, nil
    83  	default:
    84  		return nil, newError("Unsupported cipher.")
    85  	}
    86  }
    87  
    88  // AsAccount implements protocol.AsAccount.
    89  func (a *Account) AsAccount() (protocol.Account, error) {
    90  	Cipher, err := a.getCipher()
    91  	if err != nil {
    92  		return nil, newError("failed to get cipher").Base(err)
    93  	}
    94  	return &MemoryAccount{
    95  		Cipher: Cipher,
    96  		Key:    passwordToCipherKey([]byte(a.Password), Cipher.KeySize()),
    97  		replayFilter: func() antireplay.GeneralizedReplayFilter {
    98  			if a.IvCheck {
    99  				return antireplay.NewBloomRing()
   100  			}
   101  			return nil
   102  		}(),
   103  	}, nil
   104  }
   105  
   106  // Cipher is an interface for all Shadowsocks ciphers.
   107  type Cipher interface {
   108  	KeySize() int32
   109  	IVSize() int32
   110  	NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error)
   111  	NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error)
   112  	IsAEAD() bool
   113  	EncodePacket(key []byte, b *buf.Buffer) error
   114  	DecodePacket(key []byte, b *buf.Buffer) error
   115  }
   116  
   117  type AEADCipher struct {
   118  	KeyBytes        int32
   119  	IVBytes         int32
   120  	AEADAuthCreator func(key []byte) cipher.AEAD
   121  }
   122  
   123  func (*AEADCipher) IsAEAD() bool {
   124  	return true
   125  }
   126  
   127  func (c *AEADCipher) KeySize() int32 {
   128  	return c.KeyBytes
   129  }
   130  
   131  func (c *AEADCipher) IVSize() int32 {
   132  	return c.IVBytes
   133  }
   134  
   135  func (c *AEADCipher) createAuthenticator(key []byte, iv []byte) *crypto.AEADAuthenticator {
   136  	nonce := crypto.GenerateInitialAEADNonce()
   137  	subkey := make([]byte, c.KeyBytes)
   138  	hkdfSHA1(key, iv, subkey)
   139  	return &crypto.AEADAuthenticator{
   140  		AEAD:           c.AEADAuthCreator(subkey),
   141  		NonceGenerator: nonce,
   142  	}
   143  }
   144  
   145  func (c *AEADCipher) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) {
   146  	auth := c.createAuthenticator(key, iv)
   147  	return crypto.NewAuthenticationWriter(auth, &crypto.AEADChunkSizeParser{
   148  		Auth: auth,
   149  	}, writer, protocol.TransferTypeStream, nil), nil
   150  }
   151  
   152  func (c *AEADCipher) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) {
   153  	auth := c.createAuthenticator(key, iv)
   154  	return crypto.NewAuthenticationReader(auth, &crypto.AEADChunkSizeParser{
   155  		Auth: auth,
   156  	}, reader, protocol.TransferTypeStream, nil), nil
   157  }
   158  
   159  func (c *AEADCipher) EncodePacket(key []byte, b *buf.Buffer) error {
   160  	ivLen := c.IVSize()
   161  	payloadLen := b.Len()
   162  	auth := c.createAuthenticator(key, b.BytesTo(ivLen))
   163  
   164  	b.Extend(int32(auth.Overhead()))
   165  	_, err := auth.Seal(b.BytesTo(ivLen), b.BytesRange(ivLen, payloadLen))
   166  	return err
   167  }
   168  
   169  func (c *AEADCipher) DecodePacket(key []byte, b *buf.Buffer) error {
   170  	if b.Len() <= c.IVSize() {
   171  		return newError("insufficient data: ", b.Len())
   172  	}
   173  	ivLen := c.IVSize()
   174  	payloadLen := b.Len()
   175  	auth := c.createAuthenticator(key, b.BytesTo(ivLen))
   176  
   177  	bbb, err := auth.Open(b.BytesTo(ivLen), b.BytesRange(ivLen, payloadLen))
   178  	if err != nil {
   179  		return err
   180  	}
   181  	b.Resize(ivLen, int32(len(bbb)))
   182  	return nil
   183  }
   184  
   185  type NoneCipher struct{}
   186  
   187  func (NoneCipher) KeySize() int32 { return 0 }
   188  func (NoneCipher) IVSize() int32  { return 0 }
   189  func (NoneCipher) IsAEAD() bool {
   190  	return false
   191  }
   192  
   193  func (NoneCipher) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) {
   194  	return buf.NewReader(reader), nil
   195  }
   196  
   197  func (NoneCipher) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) {
   198  	return buf.NewWriter(writer), nil
   199  }
   200  
   201  func (NoneCipher) EncodePacket(key []byte, b *buf.Buffer) error {
   202  	return nil
   203  }
   204  
   205  func (NoneCipher) DecodePacket(key []byte, b *buf.Buffer) error {
   206  	return nil
   207  }
   208  
   209  func passwordToCipherKey(password []byte, keySize int32) []byte {
   210  	key := make([]byte, 0, keySize)
   211  
   212  	md5Sum := md5.Sum(password)
   213  	key = append(key, md5Sum[:]...)
   214  
   215  	for int32(len(key)) < keySize {
   216  		md5Hash := md5.New()
   217  		common.Must2(md5Hash.Write(md5Sum[:]))
   218  		common.Must2(md5Hash.Write(password))
   219  		md5Hash.Sum(md5Sum[:0])
   220  
   221  		key = append(key, md5Sum[:]...)
   222  	}
   223  	return key
   224  }
   225  
   226  func hkdfSHA1(secret, salt, outKey []byte) {
   227  	r := hkdf.New(sha1.New, secret, salt, []byte("ss-subkey"))
   228  	common.Must2(io.ReadFull(r, outKey))
   229  }