github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/proxy/shadowsocks2022/eih_aes.go (about)

     1  package shadowsocks2022
     2  
     3  import (
     4  	"crypto/subtle"
     5  	"io"
     6  
     7  	"github.com/lunixbochs/struc"
     8  
     9  	"github.com/v2fly/v2ray-core/v5/common/buf"
    10  
    11  	"lukechampine.com/blake3"
    12  )
    13  
    14  func newAESEIH(size int) *aesEIH {
    15  	return &aesEIH{length: size}
    16  }
    17  
    18  func newAESEIHWithData(size int, eih [][aesEIHSize]byte) *aesEIH {
    19  	return &aesEIH{length: size, eih: eih}
    20  }
    21  
    22  const aesEIHSize = 16
    23  
    24  type aesEIH struct {
    25  	eih    [][aesEIHSize]byte
    26  	length int
    27  }
    28  
    29  func (a *aesEIH) Pack(p []byte, opt *struc.Options) (int, error) {
    30  	var totalCopy int
    31  	for i := 0; i < a.length; i++ {
    32  		n := copy(p[aesEIHSize*i:aesEIHSize*(i+1)], a.eih[i][:])
    33  		if n != 16 {
    34  			return 0, newError("failed to pack aesEIH")
    35  		}
    36  		totalCopy += n
    37  	}
    38  	return totalCopy, nil
    39  }
    40  
    41  func (a *aesEIH) Unpack(r io.Reader, length int, opt *struc.Options) error {
    42  	a.eih = make([][aesEIHSize]byte, a.length)
    43  	for i := 0; i < a.length; i++ {
    44  		n, err := r.Read(a.eih[i][:])
    45  		if err != nil {
    46  			return newError("failed to unpack aesEIH").Base(err)
    47  		}
    48  		if n != aesEIHSize {
    49  			return newError("failed to unpack aesEIH")
    50  		}
    51  	}
    52  	return nil
    53  }
    54  
    55  func (a *aesEIH) Size(opt *struc.Options) int {
    56  	return a.length * aesEIHSize
    57  }
    58  
    59  func (a *aesEIH) String() string {
    60  	return ""
    61  }
    62  
    63  const aesEIHPskHashSize = 16
    64  
    65  type aesEIHGenerator struct {
    66  	ipsk     [][]byte
    67  	ipskHash [][aesEIHPskHashSize]byte
    68  	psk      []byte
    69  	pskHash  [aesEIHPskHashSize]byte
    70  	length   int
    71  }
    72  
    73  func newAESEIHGeneratorContainer(size int, effectivePsk []byte, ipsk [][]byte) *aesEIHGenerator {
    74  	var ipskHash [][aesEIHPskHashSize]byte
    75  	for _, v := range ipsk {
    76  		hash := blake3.Sum512(v)
    77  		ipskHash = append(ipskHash, [aesEIHPskHashSize]byte(hash[:16]))
    78  	}
    79  	pskHashFull := blake3.Sum512(effectivePsk)
    80  	pskHash := [aesEIHPskHashSize]byte(pskHashFull[:16])
    81  	return &aesEIHGenerator{length: size, ipsk: ipsk, ipskHash: ipskHash, psk: effectivePsk, pskHash: pskHash}
    82  }
    83  
    84  func (a *aesEIHGenerator) GenerateEIH(derivation KeyDerivation, method Method, salt []byte) (ExtensibleIdentityHeaders, error) {
    85  	return a.generateEIHWithMask(derivation, method, salt, nil)
    86  }
    87  
    88  func (a *aesEIHGenerator) GenerateEIHUDP(derivation KeyDerivation, method Method, mask []byte) (ExtensibleIdentityHeaders, error) {
    89  	return a.generateEIHWithMask(derivation, method, nil, mask)
    90  }
    91  
    92  func (a *aesEIHGenerator) generateEIHWithMask(derivation KeyDerivation, method Method, salt, mask []byte) (ExtensibleIdentityHeaders, error) {
    93  	eih := make([][16]byte, a.length)
    94  	current := a.length - 1
    95  	currentPskHash := a.pskHash
    96  	for {
    97  		identityKeyBuf := buf.New()
    98  		identityKey := identityKeyBuf.Extend(int32(method.GetSessionSubKeyAndSaltLength()))
    99  		if mask == nil {
   100  			err := derivation.GetIdentitySubKey(a.ipsk[current], salt, identityKey)
   101  			if err != nil {
   102  				return nil, newError("failed to get identity sub key").Base(err)
   103  			}
   104  		} else {
   105  			copy(identityKey, a.ipsk[current])
   106  		}
   107  		eih[current] = [16]byte{}
   108  		if mask != nil {
   109  			subtle.XORBytes(currentPskHash[:], mask, currentPskHash[:])
   110  		}
   111  		err := method.GenerateEIH(identityKey, currentPskHash[:], eih[current][:])
   112  		if err != nil {
   113  			return nil, newError("failed to generate EIH").Base(err)
   114  		}
   115  		current--
   116  		if current < 0 {
   117  			break
   118  		}
   119  		currentPskHash = a.ipskHash[current]
   120  		identityKeyBuf.Release()
   121  	}
   122  	return newAESEIHWithData(a.length, eih), nil
   123  }