mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-25 18:31:39 +00:00
64 lines
1.5 KiB
Go
64 lines
1.5 KiB
Go
package shadowsocks_2022
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"strings"
|
|
|
|
"lukechampine.com/blake3"
|
|
)
|
|
|
|
const (
|
|
ContextSessionSubKey = "shadowsocks 2022 session subkey"
|
|
ContextIdentitySubKey = "shadowsocks 2022 identity subkey"
|
|
)
|
|
|
|
// ParseKey decodes a base64 or raw PSK key string and validates its length
|
|
func ParseKey(key string, keyLength int) ([]byte, error) {
|
|
raw, err := base64.StdEncoding.DecodeString(key)
|
|
if err != nil {
|
|
raw = []byte(key)
|
|
}
|
|
if len(raw) != keyLength {
|
|
return nil, ErrBadKey
|
|
}
|
|
return raw, nil
|
|
}
|
|
|
|
func ParsePSKList(password string, keyLength int) ([][]byte, error) {
|
|
parts := strings.Split(password, ":")
|
|
pskList := make([][]byte, len(parts))
|
|
for i, part := range parts {
|
|
norm, err := ParseKey(part, keyLength)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pskList[i] = norm
|
|
}
|
|
return pskList, nil
|
|
}
|
|
|
|
func deriveSubKey(ctx string, psk, salt []byte, keyLength int) []byte {
|
|
var keyMaterial [64]byte
|
|
kmLen := len(psk) + len(salt)
|
|
copy(keyMaterial[:], psk)
|
|
copy(keyMaterial[len(psk):], salt)
|
|
out := make([]byte, keyLength)
|
|
blake3.DeriveKey(out, ctx, keyMaterial[:kmLen])
|
|
return out
|
|
}
|
|
|
|
func DeriveSessionSubKey(psk, salt []byte, keyLength int) []byte {
|
|
return deriveSubKey(ContextSessionSubKey, psk, salt, keyLength)
|
|
}
|
|
|
|
func DeriveIdentitySubKey(psk, salt []byte, keyLength int) []byte {
|
|
return deriveSubKey(ContextIdentitySubKey, psk, salt, keyLength)
|
|
}
|
|
|
|
func DeriveUserPSKHash(userPSK []byte) [AESBlockSize]byte {
|
|
h := blake3.Sum512(userPSK)
|
|
var out [AESBlockSize]byte
|
|
copy(out[:], h[:AESBlockSize])
|
|
return out
|
|
}
|