github.com/EagleQL/Xray-core@v1.4.3/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/xtls/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 }