Allow over length for shadowsocks 2022 psk

This commit is contained in:
世界 2022-05-12 13:48:54 +08:00
parent 69d801e651
commit f1a5f8aaa3
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
5 changed files with 48 additions and 37 deletions

View file

@ -65,7 +65,6 @@ var List = []string{
func New(method string, pskList [][]byte, secureRNG io.Reader) (shadowsocks.Method, error) {
m := &Method{
name: method,
psk: pskList[len(pskList)-1],
pskList: pskList,
secureRNG: secureRNG,
replayFilter: replay.NewCuckoo(60),
@ -85,12 +84,16 @@ func New(method string, pskList [][]byte, secureRNG io.Reader) (shadowsocks.Meth
m.constructor = newChacha20Poly1305
}
for _, psk := range pskList {
if len(psk) != m.keyLength {
for i, psk := range pskList {
if len(psk) < m.keyLength {
return nil, shadowaead.ErrBadKey
} else if len(psk) > m.keyLength {
pskList[i] = DerivePSK(psk, m.keyLength)
}
}
m.psk = pskList[len(pskList)-1]
if len(pskList) > 1 {
pskHash := make([]byte, (len(pskList)-1)*aes.BlockSize)
for i, psk := range pskList {
@ -111,10 +114,17 @@ func New(method string, pskList [][]byte, secureRNG io.Reader) (shadowsocks.Meth
case "2022-blake3-chacha20-poly1305":
m.udpCipher = newXChacha20Poly1305(m.psk)
}
return m, nil
}
func Blake3DeriveKey(psk []byte, salt []byte, keyLength int) []byte {
func DerivePSK(key []byte, keyLength int) []byte {
outKey := buf.Make(keyLength)
blake3.DeriveKey(outKey, "shadowsocks 2022 pre shared key", key)
return outKey
}
func DeriveSessionKey(psk []byte, salt []byte, keyLength int) []byte {
sessionKey := buf.Make(len(psk) + len(salt))
copy(sessionKey, psk)
copy(sessionKey[len(psk):], salt)
@ -232,7 +242,7 @@ func (c *clientConn) writeRequest(payload []byte) error {
salt := make([]byte, SaltSize)
common.Must1(io.ReadFull(c.method.secureRNG, salt))
key := Blake3DeriveKey(c.method.psk, salt, c.method.keyLength)
key := DeriveSessionKey(c.method.psk, salt, c.method.keyLength)
writer := shadowaead.NewWriter(
c.Conn,
c.method.constructor(common.Dup(key)),
@ -301,7 +311,7 @@ func (c *clientConn) readResponse() error {
return E.New("salt not unique")
}
key := Blake3DeriveKey(c.method.psk, salt, c.method.keyLength)
key := DeriveSessionKey(c.method.psk, salt, c.method.keyLength)
runtime.KeepAlive(_salt)
reader := shadowaead.NewReader(
c.Conn,
@ -516,7 +526,7 @@ func (c *clientPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
} else if sessionId == c.session.lastRemoteSessionId {
remoteCipher = c.session.lastRemoteCipher
} else {
key := Blake3DeriveKey(c.method.psk, packetHeader[:8], c.method.keyLength)
key := DeriveSessionKey(c.method.psk, packetHeader[:8], c.method.keyLength)
remoteCipher = c.method.constructor(common.Dup(key))
runtime.KeepAlive(key)
}
@ -716,7 +726,7 @@ func (m *Method) newUDPSession() *udpSession {
if m.udpCipher == nil {
sessionId := make([]byte, 8)
binary.BigEndian.PutUint64(sessionId, session.sessionId)
key := Blake3DeriveKey(m.psk, sessionId, m.keyLength)
key := DeriveSessionKey(m.psk, sessionId, m.keyLength)
session.cipher = m.constructor(common.Dup(key))
runtime.KeepAlive(key)
}

View file

@ -45,7 +45,6 @@ type Service struct {
func NewService(method string, psk []byte, secureRNG io.Reader, udpTimeout int64, handler shadowsocks.Handler) (shadowsocks.Service, error) {
s := &Service{
name: method,
psk: psk,
secureRNG: secureRNG,
replayFilter: replay.NewCuckoo(60),
handler: handler,
@ -70,17 +69,20 @@ func NewService(method string, psk []byte, secureRNG io.Reader, udpTimeout int64
s.constructor = newChacha20Poly1305
}
if len(psk) != s.keyLength {
if len(psk) < s.keyLength {
return nil, shadowaead.ErrBadKey
} else if len(psk) > s.keyLength {
psk = DerivePSK(psk, s.keyLength)
}
s.psk = psk
switch method {
case "2022-blake3-aes-128-gcm":
s.udpBlockCipher = newAES(s.psk[:])
s.udpBlockCipher = newAES(psk)
case "2022-blake3-aes-256-gcm":
s.udpBlockCipher = newAES(s.psk[:])
s.udpBlockCipher = newAES(psk)
case "2022-blake3-chacha20-poly1305":
s.udpCipher = newXChacha20Poly1305(s.psk[:])
s.udpCipher = newXChacha20Poly1305(psk)
}
return s, nil
@ -105,7 +107,7 @@ func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.M
return E.New("salt not unique")
}
requestKey := Blake3DeriveKey(s.psk[:], requestSalt, s.keyLength)
requestKey := DeriveSessionKey(s.psk, requestSalt, s.keyLength)
reader := shadowaead.NewReader(
conn,
s.constructor(common.Dup(requestKey)),
@ -176,7 +178,7 @@ func (c *serverConn) writeResponse(payload []byte) (n int, err error) {
var _salt [SaltSize]byte
salt := common.Dup(_salt[:])
common.Must1(io.ReadFull(c.secureRNG, salt))
key := Blake3DeriveKey(c.uPSK[:], salt, c.keyLength)
key := DeriveSessionKey(c.uPSK, salt, c.keyLength)
runtime.KeepAlive(_salt)
writer := shadowaead.NewWriter(
c.Conn,
@ -292,7 +294,7 @@ func (s *Service) newPacket(conn N.PacketConn, buffer *buf.Buffer, metadata M.Me
if !loaded {
session.remoteSessionId = sessionId
if packetHeader != nil {
key := Blake3DeriveKey(s.psk[:], packetHeader[:8], s.keyLength)
key := DeriveSessionKey(s.psk, packetHeader[:8], s.keyLength)
session.remoteCipher = s.constructor(common.Dup(key))
runtime.KeepAlive(key)
}
@ -437,7 +439,7 @@ func (m *Service) newUDPSession() *serverUDPSession {
if m.udpCipher == nil {
sessionId := make([]byte, 8)
binary.BigEndian.PutUint64(sessionId, session.sessionId)
key := Blake3DeriveKey(m.psk[:], sessionId, m.keyLength)
key := DeriveSessionKey(m.psk, sessionId, m.keyLength)
session.cipher = m.constructor(common.Dup(key))
runtime.KeepAlive(key)
}

View file

@ -29,9 +29,15 @@ type MultiService[U comparable] struct {
uPSKHashR map[[aes.BlockSize]byte]U
}
func (s *MultiService[U]) AddUser(user U, key []byte) {
func (s *MultiService[U]) AddUser(user U, key []byte) error {
if len(key) < s.keyLength {
return shadowaead.ErrBadKey
} else if len(key) > s.keyLength {
key = DerivePSK(key, s.keyLength)
}
var uPSKHash [aes.BlockSize]byte
hash512 := blake3.Sum512(key[:])
hash512 := blake3.Sum512(key)
copy(uPSKHash[:], hash512[:])
if oldHash, loaded := s.uPSKHash[user]; loaded {
@ -40,8 +46,9 @@ func (s *MultiService[U]) AddUser(user U, key []byte) {
s.uPSKHash[user] = uPSKHash
s.uPSKHashR[uPSKHash] = user
s.uPSK[user] = key
return nil
}
func (s *MultiService[U]) RemoveUser(user U) {
@ -102,7 +109,7 @@ func (s *MultiService[U]) newConnection(ctx context.Context, conn net.Conn, meta
}
keyMaterial := buf.Make(s.keyLength + SaltSize)
copy(keyMaterial, s.psk[:])
copy(keyMaterial, s.psk)
copy(keyMaterial[s.keyLength:], requestSalt)
_identitySubkey := buf.Make(s.keyLength)
identitySubkey := common.Dup(_identitySubkey)
@ -119,7 +126,7 @@ func (s *MultiService[U]) newConnection(ctx context.Context, conn net.Conn, meta
return E.New("invalid request")
}
requestKey := Blake3DeriveKey(uPSK[:], requestSalt, s.keyLength)
requestKey := DeriveSessionKey(uPSK, requestSalt, s.keyLength)
reader := shadowaead.NewReader(
conn,
s.constructor(common.Dup(requestKey)),
@ -223,7 +230,7 @@ func (s *MultiService[U]) newPacket(conn N.PacketConn, buffer *buf.Buffer, metad
})
if !loaded {
session.remoteSessionId = sessionId
key := Blake3DeriveKey(uPSK[:], packetHeader[:8], s.keyLength)
key := DeriveSessionKey(uPSK, packetHeader[:8], s.keyLength)
session.remoteCipher = s.constructor(common.Dup(key))
runtime.KeepAlive(key)
}
@ -305,7 +312,7 @@ func (m *MultiService[U]) newUDPSession(uPSK []byte) *serverUDPSession {
session.packetId--
sessionId := make([]byte, 8)
binary.BigEndian.PutUint64(sessionId, session.sessionId)
key := Blake3DeriveKey(uPSK[:], sessionId, m.keyLength)
key := DeriveSessionKey(uPSK, sessionId, m.keyLength)
session.cipher = m.constructor(common.Dup(key))
runtime.KeepAlive(key)
return session