cipher.go 1.2 KB

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