github.com/kelleygo/clashcore@v1.0.2/transport/snell/cipher.go (about)

     1  package snell
     2  
     3  import (
     4  	"crypto/aes"
     5  	"crypto/cipher"
     6  
     7  	"github.com/kelleygo/clashcore/transport/shadowsocks/shadowaead"
     8  
     9  	"golang.org/x/crypto/argon2"
    10  	"golang.org/x/crypto/chacha20poly1305"
    11  )
    12  
    13  type snellCipher struct {
    14  	psk      []byte
    15  	keySize  int
    16  	makeAEAD func(key []byte) (cipher.AEAD, error)
    17  }
    18  
    19  func (sc *snellCipher) KeySize() int  { return sc.keySize }
    20  func (sc *snellCipher) SaltSize() int { return 16 }
    21  func (sc *snellCipher) Encrypter(salt []byte) (cipher.AEAD, error) {
    22  	return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize()))
    23  }
    24  
    25  func (sc *snellCipher) Decrypter(salt []byte) (cipher.AEAD, error) {
    26  	return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize()))
    27  }
    28  
    29  func snellKDF(psk, salt []byte, keySize int) []byte {
    30  	// snell use a special kdf function
    31  	return argon2.IDKey(psk, salt, 3, 8, 1, 32)[:keySize]
    32  }
    33  
    34  func aesGCM(key []byte) (cipher.AEAD, error) {
    35  	blk, err := aes.NewCipher(key)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	return cipher.NewGCM(blk)
    40  }
    41  
    42  func NewAES128GCM(psk []byte) shadowaead.Cipher {
    43  	return &snellCipher{
    44  		psk:      psk,
    45  		keySize:  16,
    46  		makeAEAD: aesGCM,
    47  	}
    48  }
    49  
    50  func NewChacha20Poly1305(psk []byte) shadowaead.Cipher {
    51  	return &snellCipher{
    52  		psk:      psk,
    53  		keySize:  32,
    54  		makeAEAD: chacha20poly1305.New,
    55  	}
    56  }