github.com/metacubex/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 }