mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-23 02:26:49 -05:00
124 lines
3.2 KiB
Go
124 lines
3.2 KiB
Go
package shadowsocks2022
|
|
|
|
import (
|
|
"crypto/subtle"
|
|
"io"
|
|
|
|
"github.com/lunixbochs/struc"
|
|
|
|
"github.com/v2fly/v2ray-core/v5/common/buf"
|
|
|
|
"lukechampine.com/blake3"
|
|
)
|
|
|
|
func newAESEIH(size int) *aesEIH {
|
|
return &aesEIH{length: size}
|
|
}
|
|
|
|
func newAESEIHWithData(size int, eih [][aesEIHSize]byte) *aesEIH {
|
|
return &aesEIH{length: size, eih: eih}
|
|
}
|
|
|
|
const aesEIHSize = 16
|
|
|
|
type aesEIH struct {
|
|
eih [][aesEIHSize]byte
|
|
length int
|
|
}
|
|
|
|
func (a *aesEIH) Pack(p []byte, opt *struc.Options) (int, error) {
|
|
var totalCopy int
|
|
for i := 0; i < a.length; i++ {
|
|
n := copy(p[aesEIHSize*i:aesEIHSize*(i+1)], a.eih[i][:])
|
|
if n != 16 {
|
|
return 0, newError("failed to pack aesEIH")
|
|
}
|
|
totalCopy += n
|
|
}
|
|
return totalCopy, nil
|
|
}
|
|
|
|
func (a *aesEIH) Unpack(r io.Reader, length int, opt *struc.Options) error {
|
|
a.eih = make([][aesEIHSize]byte, a.length)
|
|
for i := 0; i < a.length; i++ {
|
|
n, err := r.Read(a.eih[i][:])
|
|
if err != nil {
|
|
return newError("failed to unpack aesEIH").Base(err)
|
|
}
|
|
if n != aesEIHSize {
|
|
return newError("failed to unpack aesEIH")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (a *aesEIH) Size(opt *struc.Options) int {
|
|
return a.length * aesEIHSize
|
|
}
|
|
|
|
func (a *aesEIH) String() string {
|
|
return ""
|
|
}
|
|
|
|
const aesEIHPskHashSize = 16
|
|
|
|
type aesEIHGenerator struct {
|
|
ipsk [][]byte
|
|
ipskHash [][aesEIHPskHashSize]byte
|
|
psk []byte
|
|
pskHash [aesEIHPskHashSize]byte
|
|
length int
|
|
}
|
|
|
|
func newAESEIHGeneratorContainer(size int, effectivePsk []byte, ipsk [][]byte) *aesEIHGenerator {
|
|
var ipskHash [][aesEIHPskHashSize]byte
|
|
for _, v := range ipsk {
|
|
hash := blake3.Sum512(v)
|
|
ipskHash = append(ipskHash, [aesEIHPskHashSize]byte(hash[:16]))
|
|
}
|
|
pskHashFull := blake3.Sum512(effectivePsk)
|
|
pskHash := [aesEIHPskHashSize]byte(pskHashFull[:16])
|
|
return &aesEIHGenerator{length: size, ipsk: ipsk, ipskHash: ipskHash, psk: effectivePsk, pskHash: pskHash}
|
|
}
|
|
|
|
func (a *aesEIHGenerator) GenerateEIH(derivation KeyDerivation, method Method, salt []byte) (ExtensibleIdentityHeaders, error) {
|
|
return a.generateEIHWithMask(derivation, method, salt, nil)
|
|
}
|
|
|
|
func (a *aesEIHGenerator) GenerateEIHUDP(derivation KeyDerivation, method Method, mask []byte) (ExtensibleIdentityHeaders, error) {
|
|
return a.generateEIHWithMask(derivation, method, nil, mask)
|
|
}
|
|
|
|
func (a *aesEIHGenerator) generateEIHWithMask(derivation KeyDerivation, method Method, salt, mask []byte) (ExtensibleIdentityHeaders, error) {
|
|
eih := make([][16]byte, a.length)
|
|
current := a.length - 1
|
|
currentPskHash := a.pskHash
|
|
for {
|
|
identityKeyBuf := buf.New()
|
|
identityKey := identityKeyBuf.Extend(int32(method.GetSessionSubKeyAndSaltLength()))
|
|
if mask == nil {
|
|
err := derivation.GetIdentitySubKey(a.ipsk[current], salt, identityKey)
|
|
if err != nil {
|
|
return nil, newError("failed to get identity sub key").Base(err)
|
|
}
|
|
} else {
|
|
copy(identityKey, a.ipsk[current])
|
|
}
|
|
eih[current] = [16]byte{}
|
|
if mask != nil {
|
|
subtle.XORBytes(currentPskHash[:], mask, currentPskHash[:])
|
|
}
|
|
err := method.GenerateEIH(identityKey, currentPskHash[:], eih[current][:])
|
|
if err != nil {
|
|
return nil, newError("failed to generate EIH").Base(err)
|
|
}
|
|
current--
|
|
if current < 0 {
|
|
break
|
|
}
|
|
currentPskHash = a.ipskHash[current]
|
|
identityKeyBuf.Release()
|
|
}
|
|
return newAESEIHWithData(a.length, eih), nil
|
|
}
|