github.com/sagernet/sing-shadowsocks2@v0.2.0/shadowaead_2022/protocol.go (about)

     1  package shadowaead_2022
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"crypto/sha256"
     6  	"io"
     7  	"sync/atomic"
     8  
     9  	"github.com/sagernet/sing/common"
    10  	E "github.com/sagernet/sing/common/exceptions"
    11  	"github.com/sagernet/sing/common/random"
    12  
    13  	"lukechampine.com/blake3"
    14  )
    15  
    16  const (
    17  	HeaderTypeClient              = 0
    18  	HeaderTypeServer              = 1
    19  	MaxPaddingLength              = 900
    20  	PacketNonceSize               = 24
    21  	RequestHeaderFixedChunkLength = 1 + 8 + 2
    22  	PacketMinimalHeaderSize       = 30
    23  )
    24  
    25  var (
    26  	ErrNoEIH                 = E.New("Shadowsocks 2022 EIH support only available in AES ciphers")
    27  	ErrBadHeaderType         = E.New("bad header type")
    28  	ErrBadTimestamp          = E.New("bad timestamp")
    29  	ErrBadRequestSalt        = E.New("bad request salt")
    30  	ErrSaltNotUnique         = E.New("salt not unique")
    31  	ErrBadClientSessionId    = E.New("bad client session id")
    32  	ErrPacketIdNotUnique     = E.New("packet id not unique")
    33  	ErrTooManyServerSessions = E.New("server session changed more than once during the last minute")
    34  )
    35  
    36  func init() {
    37  	random.InitializeSeed()
    38  }
    39  
    40  func Key(key []byte, keyLength int) []byte {
    41  	psk := sha256.Sum256(key)
    42  	return psk[:keyLength]
    43  }
    44  
    45  func SessionKey(psk []byte, salt []byte, keyLength int) []byte {
    46  	sessionKey := make([]byte, len(psk)+len(salt))
    47  	copy(sessionKey, psk)
    48  	copy(sessionKey[len(psk):], salt)
    49  	outKey := make([]byte, keyLength)
    50  	blake3.DeriveKey(outKey, "shadowsocks 2022 session subkey", sessionKey)
    51  	return outKey
    52  }
    53  
    54  func aeadCipher(block func(key []byte) (cipher.Block, error), aead func(block cipher.Block) (cipher.AEAD, error)) func(key []byte) (cipher.AEAD, error) {
    55  	return func(key []byte) (cipher.AEAD, error) {
    56  		b, err := block(key)
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		return aead(b)
    61  	}
    62  }
    63  
    64  type udpSession struct {
    65  	sessionId           uint64
    66  	packetId            uint64
    67  	remoteSessionId     uint64
    68  	lastRemoteSessionId uint64
    69  	lastRemoteSeen      int64
    70  	cipher              cipher.AEAD
    71  	remoteCipher        cipher.AEAD
    72  	lastRemoteCipher    cipher.AEAD
    73  	window              SlidingWindow
    74  	lastWindow          SlidingWindow
    75  	rng                 io.Reader
    76  }
    77  
    78  func (s *udpSession) nextPacketId() uint64 {
    79  	return atomic.AddUint64(&s.packetId, 1)
    80  }
    81  
    82  func Blake3KeyedHash(reader io.Reader) io.Reader {
    83  	key := make([]byte, 32)
    84  	common.Must1(io.ReadFull(reader, key))
    85  	h := blake3.New(1024, key)
    86  	return h.XOF()
    87  }