github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/vmess/tools.go (about) 1 package vmess 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "crypto/hmac" 8 rand3 "crypto/rand" 9 "crypto/sha256" 10 "encoding/binary" 11 "fmt" 12 "hash" 13 "hash/crc32" 14 "io" 15 "net" 16 "time" 17 18 "github.com/Asutorufa/yuhaiin/pkg/utils/pool" 19 "github.com/Asutorufa/yuhaiin/pkg/utils/relay" 20 ) 21 22 // copy from https://github.com/v2fly/v2ray-core/tree/054e6679830885c94cc37d27ab2aa96b5b37e019/proxy/vmess/aead 23 const ( 24 KDFSaltConstAuthIDEncryptionKey = "AES Auth ID Encryption" 25 KDFSaltConstAEADRespHeaderLenKey = "AEAD Resp Header Len Key" 26 KDFSaltConstAEADRespHeaderLenIV = "AEAD Resp Header Len IV" 27 KDFSaltConstAEADRespHeaderPayloadKey = "AEAD Resp Header Key" 28 KDFSaltConstAEADRespHeaderPayloadIV = "AEAD Resp Header IV" 29 KDFSaltConstVMessAEADKDF = "VMess AEAD KDF" 30 KDFSaltConstVMessHeaderPayloadAEADKey = "VMess Header AEAD Key" 31 KDFSaltConstVMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce" 32 KDFSaltConstVMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length" 33 KDFSaltConstVMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length" 34 ) 35 36 func KDF(key []byte, path ...string) []byte { 37 hmacCreator := &hMacCreator{value: []byte(KDFSaltConstVMessAEADKDF)} 38 for _, v := range path { 39 hmacCreator = &hMacCreator{value: []byte(v), parent: hmacCreator} 40 } 41 hmacf := hmacCreator.Create() 42 hmacf.Write(key) 43 return hmacf.Sum(nil) 44 } 45 46 type hMacCreator struct { 47 parent *hMacCreator 48 value []byte 49 } 50 51 func (h *hMacCreator) Create() hash.Hash { 52 if h.parent == nil { 53 return hmac.New(sha256.New, h.value) 54 } 55 return hmac.New(h.parent.Create, h.value) 56 } 57 58 func KDF16(key []byte, path ...string) []byte { 59 r := KDF(key, path...) 60 return r[:16] 61 } 62 63 func CreateAuthID(cmdKey []byte, time int64) [16]byte { 64 buf := pool.GetBytesWriter(pool.DefaultSize) 65 defer buf.Free() 66 67 _ = binary.Write(buf, binary.BigEndian, time) 68 _, _ = relay.CopyN(buf, rand3.Reader, 4) 69 zero := crc32.ChecksumIEEE(buf.Bytes()) 70 _ = binary.Write(buf, binary.BigEndian, zero) 71 aesBlock := NewCipherFromKey(cmdKey) 72 if buf.Len() != 16 { 73 panic("Size unexpected") 74 } 75 var result [16]byte 76 aesBlock.Encrypt(result[:], buf.Bytes()) 77 return result 78 } 79 80 func NewCipherFromKey(cmdKey []byte) cipher.Block { 81 aesBlock, err := aes.NewCipher(KDF16(cmdKey, KDFSaltConstAuthIDEncryptionKey)) 82 if err != nil { 83 panic(err) 84 } 85 return aesBlock 86 } 87 88 func SealVMessAEADHeader(key [16]byte, data []byte) []byte { 89 generatedAuthID := CreateAuthID(key[:], time.Now().Unix()) 90 91 connectionNonce := pool.GetBytes(8) 92 defer pool.PutBytes(connectionNonce) 93 94 connectionNonce = connectionNonce[:8] 95 if _, err := io.ReadFull(rand3.Reader, connectionNonce); err != nil { 96 panic(err.Error()) 97 } 98 99 aeadPayloadLengthSerializeBuffer := bytes.NewBuffer(nil) 100 headerPayloadDataLen := uint16(len(data)) 101 _ = binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen) 102 aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes() 103 104 var payloadHeaderLengthAEADEncrypted []byte 105 106 { 107 payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce)) 108 109 payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12] 110 111 payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey) 112 if err != nil { 113 panic(err.Error()) 114 } 115 116 payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderLengthAEADAESBlock) 117 if err != nil { 118 panic(err.Error()) 119 } 120 121 payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:]) 122 } 123 124 var payloadHeaderAEADEncrypted []byte 125 126 { 127 payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce)) 128 129 payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12] 130 131 payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey) 132 if err != nil { 133 panic(err.Error()) 134 } 135 136 payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) 137 if err != nil { 138 panic(err.Error()) 139 } 140 141 payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:]) 142 } 143 144 outputBuffer := bytes.NewBuffer(nil) 145 146 outputBuffer.Write(generatedAuthID[:]) // 16 147 outputBuffer.Write(payloadHeaderLengthAEADEncrypted) // 2+16 148 outputBuffer.Write(connectionNonce) // 8 149 outputBuffer.Write(payloadHeaderAEADEncrypted) 150 151 return outputBuffer.Bytes() 152 } 153 154 func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, int, error) { 155 var payloadHeaderLengthAEADEncrypted [18]byte 156 var nonce [8]byte 157 158 var bytesRead int 159 160 authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:]) 161 bytesRead += authidCheckValueReadBytesCounts 162 if err != nil { 163 return nil, false, bytesRead, err 164 } 165 166 nonceReadBytesCounts, err := io.ReadFull(data, nonce[:]) 167 bytesRead += nonceReadBytesCounts 168 if err != nil { 169 return nil, false, bytesRead, err 170 } 171 172 // Decrypt Length 173 174 var decryptedAEADHeaderLengthPayloadResult []byte 175 176 { 177 payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:])) 178 179 payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12] 180 181 payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey) 182 if err != nil { 183 panic(err.Error()) 184 } 185 186 payloadHeaderLengthAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) 187 if err != nil { 188 panic(err.Error()) 189 } 190 191 decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:]) 192 193 if erropenAEAD != nil { 194 return nil, true, bytesRead, erropenAEAD 195 } 196 197 decryptedAEADHeaderLengthPayloadResult = decryptedAEADHeaderLengthPayload 198 } 199 200 var length uint16 201 202 _ = binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult), binary.BigEndian, &length) 203 204 var decryptedAEADHeaderPayloadR []byte 205 206 var payloadHeaderAEADEncryptedReadedBytesCounts int 207 208 { 209 payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:])) 210 211 payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12] 212 213 // 16 == AEAD Tag size 214 payloadHeaderAEADEncrypted := make([]byte, length+16) 215 216 payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted) 217 bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts 218 if err != nil { 219 return nil, false, bytesRead, err 220 } 221 222 payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey) 223 if err != nil { 224 panic(err.Error()) 225 } 226 227 payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) 228 if err != nil { 229 panic(err.Error()) 230 } 231 232 decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, nil) 233 234 if erropenAEAD != nil { 235 return nil, true, bytesRead, erropenAEAD 236 } 237 238 decryptedAEADHeaderPayloadR = decryptedAEADHeaderPayload 239 } 240 241 return decryptedAEADHeaderPayloadR, false, bytesRead, nil 242 } 243 244 // from https://github.com/v2ray/v2ray-core/blob/5dffca84234a74da9e8174f1e0b0af3dfb2a58ce/proxy/vmess/encoding/client.go#L191 245 func DecodeResponseHeader(responseBodyKey, responseBodyIV []byte, reader net.Conn) ([]byte, error) { 246 aeadResponseHeaderLengthEncryptionKey := KDF16(responseBodyKey[:], KDFSaltConstAEADRespHeaderLenKey) 247 aeadResponseHeaderLengthEncryptionIV := KDF(responseBodyIV[:], KDFSaltConstAEADRespHeaderLenIV)[:12] 248 249 aeadResponseHeaderLengthEncryptionKeyAESBlock, err := aes.NewCipher(aeadResponseHeaderLengthEncryptionKey) 250 if err != nil { 251 return nil, fmt.Errorf("create aes cipher failed: %w", err) 252 } 253 aeadResponseHeaderLengthEncryptionAEAD, err := cipher.NewGCM(aeadResponseHeaderLengthEncryptionKeyAESBlock) 254 if err != nil { 255 return nil, fmt.Errorf("create aead failed: %w", err) 256 } 257 258 var aeadEncryptedResponseHeaderLength [18]byte 259 var decryptedResponseHeaderLength int 260 var decryptedResponseHeaderLengthBinaryDeserializeBuffer uint16 261 262 if _, err := io.ReadFull(reader, aeadEncryptedResponseHeaderLength[:]); err != nil { 263 return nil, fmt.Errorf("read encrypted response header length failed: %w", err) 264 } 265 if decryptedResponseHeaderLengthBinaryBuffer, err := aeadResponseHeaderLengthEncryptionAEAD.Open(nil, aeadResponseHeaderLengthEncryptionIV, aeadEncryptedResponseHeaderLength[:], nil); err != nil { 266 return nil, fmt.Errorf("decrypt response header length failed: %w", err) 267 } else { 268 _ = binary.Read(bytes.NewReader(decryptedResponseHeaderLengthBinaryBuffer), binary.BigEndian, &decryptedResponseHeaderLengthBinaryDeserializeBuffer) 269 decryptedResponseHeaderLength = int(decryptedResponseHeaderLengthBinaryDeserializeBuffer) 270 } 271 272 aeadResponseHeaderPayloadEncryptionKey := KDF16(responseBodyKey[:], KDFSaltConstAEADRespHeaderPayloadKey) 273 aeadResponseHeaderPayloadEncryptionIV := KDF(responseBodyIV[:], KDFSaltConstAEADRespHeaderPayloadIV)[:12] 274 275 aeadResponseHeaderPayloadEncryptionKeyAESBlock, err := aes.NewCipher(aeadResponseHeaderPayloadEncryptionKey) 276 if err != nil { 277 return nil, fmt.Errorf("create aes cipher failed: %w", err) 278 } 279 aeadResponseHeaderPayloadEncryptionAEAD, err := cipher.NewGCM(aeadResponseHeaderPayloadEncryptionKeyAESBlock) 280 if err != nil { 281 return nil, fmt.Errorf("create aead failed: %w", err) 282 } 283 284 encryptedResponseHeaderBuffer := make([]byte, decryptedResponseHeaderLength+16) 285 286 if _, err := io.ReadFull(reader, encryptedResponseHeaderBuffer); err != nil { 287 return nil, fmt.Errorf("read encrypted response header failed: %w", err) 288 } 289 290 decryptedResponseHeaderBuffer, err := aeadResponseHeaderPayloadEncryptionAEAD.Open(nil, aeadResponseHeaderPayloadEncryptionIV, encryptedResponseHeaderBuffer, nil) 291 if err != nil { 292 return nil, fmt.Errorf("decrypt response header failed: %w", err) 293 } 294 295 return decryptedResponseHeaderBuffer, nil 296 }