github.com/xraypb/Xray-core@v1.8.1/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/xraypb/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  		if err != nil {
    44  			panic(err.Error())
    45  		}
    46  
    47  		payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
    48  	}
    49  
    50  	var payloadHeaderAEADEncrypted []byte
    51  
    52  	{
    53  		payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
    54  
    55  		payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
    56  
    57  		payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
    58  		if err != nil {
    59  			panic(err.Error())
    60  		}
    61  
    62  		payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
    63  		if err != nil {
    64  			panic(err.Error())
    65  		}
    66  
    67  		payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
    68  	}
    69  
    70  	outputBuffer := bytes.NewBuffer(nil)
    71  
    72  	common.Must2(outputBuffer.Write(generatedAuthID[:]))               // 16
    73  	common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) // 2+16
    74  	common.Must2(outputBuffer.Write(connectionNonce))                  // 8
    75  	common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted))
    76  
    77  	return outputBuffer.Bytes()
    78  }
    79  
    80  func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, int, error) {
    81  	var payloadHeaderLengthAEADEncrypted [18]byte
    82  	var nonce [8]byte
    83  
    84  	var bytesRead int
    85  
    86  	authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:])
    87  	bytesRead += authidCheckValueReadBytesCounts
    88  	if err != nil {
    89  		return nil, false, bytesRead, err
    90  	}
    91  
    92  	nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
    93  	bytesRead += nonceReadBytesCounts
    94  	if err != nil {
    95  		return nil, false, bytesRead, err
    96  	}
    97  
    98  	// Decrypt Length
    99  
   100  	var decryptedAEADHeaderLengthPayloadResult []byte
   101  
   102  	{
   103  		payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:]))
   104  
   105  		payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
   106  
   107  		payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
   108  		if err != nil {
   109  			panic(err.Error())
   110  		}
   111  
   112  		payloadHeaderLengthAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
   113  		if err != nil {
   114  			panic(err.Error())
   115  		}
   116  
   117  		decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:])
   118  
   119  		if erropenAEAD != nil {
   120  			return nil, true, bytesRead, erropenAEAD
   121  		}
   122  
   123  		decryptedAEADHeaderLengthPayloadResult = decryptedAEADHeaderLengthPayload
   124  	}
   125  
   126  	var length uint16
   127  
   128  	common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult), binary.BigEndian, &length))
   129  
   130  	var decryptedAEADHeaderPayloadR []byte
   131  
   132  	var payloadHeaderAEADEncryptedReadedBytesCounts int
   133  
   134  	{
   135  		payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
   136  
   137  		payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
   138  
   139  		// 16 == AEAD Tag size
   140  		payloadHeaderAEADEncrypted := make([]byte, length+16)
   141  
   142  		payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted)
   143  		bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts
   144  		if err != nil {
   145  			return nil, false, bytesRead, err
   146  		}
   147  
   148  		payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
   149  		if err != nil {
   150  			panic(err.Error())
   151  		}
   152  
   153  		payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
   154  		if err != nil {
   155  			panic(err.Error())
   156  		}
   157  
   158  		decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
   159  
   160  		if erropenAEAD != nil {
   161  			return nil, true, bytesRead, erropenAEAD
   162  		}
   163  
   164  		decryptedAEADHeaderPayloadR = decryptedAEADHeaderPayload
   165  	}
   166  
   167  	return decryptedAEADHeaderPayloadR, false, bytesRead, nil
   168  }