github.com/laof/lite-speed-test@v0.0.0-20230930011949-1f39b7037845/transport/vmess/header.go (about)

     1  package vmess
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"crypto/hmac"
     8  	"crypto/rand"
     9  	"crypto/sha256"
    10  	"encoding/binary"
    11  	"hash"
    12  	"hash/crc32"
    13  	"time"
    14  )
    15  
    16  const (
    17  	kdfSaltConstAuthIDEncryptionKey             = "AES Auth ID Encryption"
    18  	kdfSaltConstAEADRespHeaderLenKey            = "AEAD Resp Header Len Key"
    19  	kdfSaltConstAEADRespHeaderLenIV             = "AEAD Resp Header Len IV"
    20  	kdfSaltConstAEADRespHeaderPayloadKey        = "AEAD Resp Header Key"
    21  	kdfSaltConstAEADRespHeaderPayloadIV         = "AEAD Resp Header IV"
    22  	kdfSaltConstVMessAEADKDF                    = "VMess AEAD KDF"
    23  	kdfSaltConstVMessHeaderPayloadAEADKey       = "VMess Header AEAD Key"
    24  	kdfSaltConstVMessHeaderPayloadAEADIV        = "VMess Header AEAD Nonce"
    25  	kdfSaltConstVMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
    26  	kdfSaltConstVMessHeaderPayloadLengthAEADIV  = "VMess Header AEAD Nonce_Length"
    27  )
    28  
    29  func kdf(key []byte, path ...string) []byte {
    30  	hmacCreator := &hMacCreator{value: []byte(kdfSaltConstVMessAEADKDF)}
    31  	for _, v := range path {
    32  		hmacCreator = &hMacCreator{value: []byte(v), parent: hmacCreator}
    33  	}
    34  	hmacf := hmacCreator.Create()
    35  	hmacf.Write(key)
    36  	return hmacf.Sum(nil)
    37  }
    38  
    39  type hMacCreator struct {
    40  	parent *hMacCreator
    41  	value  []byte
    42  }
    43  
    44  func (h *hMacCreator) Create() hash.Hash {
    45  	if h.parent == nil {
    46  		return hmac.New(sha256.New, h.value)
    47  	}
    48  	return hmac.New(h.parent.Create, h.value)
    49  }
    50  
    51  func createAuthID(cmdKey []byte, time int64) [16]byte {
    52  	buf := &bytes.Buffer{}
    53  	binary.Write(buf, binary.BigEndian, time)
    54  
    55  	random := make([]byte, 4)
    56  	rand.Read(random)
    57  	buf.Write(random)
    58  	zero := crc32.ChecksumIEEE(buf.Bytes())
    59  	binary.Write(buf, binary.BigEndian, zero)
    60  
    61  	aesBlock, _ := aes.NewCipher(kdf(cmdKey[:], kdfSaltConstAuthIDEncryptionKey)[:16])
    62  	var result [16]byte
    63  	aesBlock.Encrypt(result[:], buf.Bytes())
    64  	return result
    65  }
    66  
    67  func sealVMessAEADHeader(key [16]byte, data []byte, t time.Time) []byte {
    68  	generatedAuthID := createAuthID(key[:], t.Unix())
    69  	connectionNonce := make([]byte, 8)
    70  	rand.Read(connectionNonce)
    71  
    72  	aeadPayloadLengthSerializedByte := make([]byte, 2)
    73  	binary.BigEndian.PutUint16(aeadPayloadLengthSerializedByte, uint16(len(data)))
    74  
    75  	var payloadHeaderLengthAEADEncrypted []byte
    76  
    77  	{
    78  		payloadHeaderLengthAEADKey := kdf(key[:], kdfSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))[:16]
    79  		payloadHeaderLengthAEADNonce := kdf(key[:], kdfSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
    80  		payloadHeaderLengthAEADAESBlock, _ := aes.NewCipher(payloadHeaderLengthAEADKey)
    81  		payloadHeaderAEAD, _ := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
    82  		payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
    83  	}
    84  
    85  	var payloadHeaderAEADEncrypted []byte
    86  
    87  	{
    88  		payloadHeaderAEADKey := kdf(key[:], kdfSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))[:16]
    89  		payloadHeaderAEADNonce := kdf(key[:], kdfSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
    90  		payloadHeaderAEADAESBlock, _ := aes.NewCipher(payloadHeaderAEADKey)
    91  		payloadHeaderAEAD, _ := cipher.NewGCM(payloadHeaderAEADAESBlock)
    92  		payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
    93  	}
    94  
    95  	var outputBuffer = &bytes.Buffer{}
    96  
    97  	outputBuffer.Write(generatedAuthID[:])
    98  	outputBuffer.Write(payloadHeaderLengthAEADEncrypted)
    99  	outputBuffer.Write(connectionNonce)
   100  	outputBuffer.Write(payloadHeaderAEADEncrypted)
   101  
   102  	return outputBuffer.Bytes()
   103  }