github.com/eagleql/xray-core@v1.4.4/proxy/vmess/aead/encrypt.go (about)

     1  package aead
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"crypto/rand"
     8  	"encoding/binary"
     9  	"io"
    10  	"time"
    11  
    12  	"github.com/eagleql/xray-core/common"
    13  )
    14  
    15  func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
    16  	generatedAuthID := CreateAuthID(key[:], time.Now().Unix())
    17  
    18  	connectionNonce := make([]byte, 8)
    19  	if _, err := io.ReadFull(rand.Reader, connectionNonce); err != nil {
    20  		panic(err.Error())
    21  	}
    22  
    23  	aeadPayloadLengthSerializeBuffer := bytes.NewBuffer(nil)
    24  
    25  	headerPayloadDataLen := uint16(len(data))
    26  
    27  	common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen))
    28  
    29  	aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes()
    30  	var payloadHeaderLengthAEADEncrypted []byte
    31  
    32  	{
    33  		payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))
    34  
    35  		payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
    36  
    37  		payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
    38  		if err != nil {
    39  			panic(err.Error())
    40  		}
    41  
    42  		payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
    43  
    44  		if err != nil {
    45  			panic(err.Error())
    46  		}
    47  
    48  		payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
    49  	}
    50  
    51  	var payloadHeaderAEADEncrypted []byte
    52  
    53  	{
    54  		payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
    55  
    56  		payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
    57  
    58  		payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
    59  		if err != nil {
    60  			panic(err.Error())
    61  		}
    62  
    63  		payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
    64  
    65  		if err != nil {
    66  			panic(err.Error())
    67  		}
    68  
    69  		payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
    70  	}
    71  
    72  	var outputBuffer = bytes.NewBuffer(nil)
    73  
    74  	common.Must2(outputBuffer.Write(generatedAuthID[:]))               // 16
    75  	common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) // 2+16
    76  	common.Must2(outputBuffer.Write(connectionNonce))                  // 8
    77  	common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted))
    78  
    79  	return outputBuffer.Bytes()
    80  }
    81  
    82  func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, int, error) {
    83  	var payloadHeaderLengthAEADEncrypted [18]byte
    84  	var nonce [8]byte
    85  
    86  	var bytesRead int
    87  
    88  	authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:])
    89  	bytesRead += authidCheckValueReadBytesCounts
    90  	if err != nil {
    91  		return nil, false, bytesRead, err
    92  	}
    93  
    94  	nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
    95  	bytesRead += nonceReadBytesCounts
    96  	if err != nil {
    97  		return nil, false, bytesRead, err
    98  	}
    99  
   100  	// Decrypt Length
   101  
   102  	var decryptedAEADHeaderLengthPayloadResult []byte
   103  
   104  	{
   105  		payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:]))
   106  
   107  		payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
   108  
   109  		payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
   110  		if err != nil {
   111  			panic(err.Error())
   112  		}
   113  
   114  		payloadHeaderLengthAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
   115  
   116  		if err != nil {
   117  			panic(err.Error())
   118  		}
   119  
   120  		decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:])
   121  
   122  		if erropenAEAD != nil {
   123  			return nil, true, bytesRead, erropenAEAD
   124  		}
   125  
   126  		decryptedAEADHeaderLengthPayloadResult = decryptedAEADHeaderLengthPayload
   127  	}
   128  
   129  	var length uint16
   130  
   131  	common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult), binary.BigEndian, &length))
   132  
   133  	var decryptedAEADHeaderPayloadR []byte
   134  
   135  	var payloadHeaderAEADEncryptedReadedBytesCounts int
   136  
   137  	{
   138  		payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
   139  
   140  		payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
   141  
   142  		// 16 == AEAD Tag size
   143  		payloadHeaderAEADEncrypted := make([]byte, length+16)
   144  
   145  		payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted)
   146  		bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts
   147  		if err != nil {
   148  			return nil, false, bytesRead, err
   149  		}
   150  
   151  		payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
   152  		if err != nil {
   153  			panic(err.Error())
   154  		}
   155  
   156  		payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
   157  
   158  		if err != nil {
   159  			panic(err.Error())
   160  		}
   161  
   162  		decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
   163  
   164  		if erropenAEAD != nil {
   165  			return nil, true, bytesRead, erropenAEAD
   166  		}
   167  
   168  		decryptedAEADHeaderPayloadR = decryptedAEADHeaderPayload
   169  	}
   170  
   171  	return decryptedAEADHeaderPayloadR, false, bytesRead, nil
   172  }