Chore: split component to transport
This commit is contained in:
103
transport/vmess/header.go
Normal file
103
transport/vmess/header.go
Normal file
@ -0,0 +1,103 @@
|
||||
package vmess
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
"hash/crc32"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
kdfSaltConstAuthIDEncryptionKey = "AES Auth ID Encryption"
|
||||
kdfSaltConstAEADRespHeaderLenKey = "AEAD Resp Header Len Key"
|
||||
kdfSaltConstAEADRespHeaderLenIV = "AEAD Resp Header Len IV"
|
||||
kdfSaltConstAEADRespHeaderPayloadKey = "AEAD Resp Header Key"
|
||||
kdfSaltConstAEADRespHeaderPayloadIV = "AEAD Resp Header IV"
|
||||
kdfSaltConstVMessAEADKDF = "VMess AEAD KDF"
|
||||
kdfSaltConstVMessHeaderPayloadAEADKey = "VMess Header AEAD Key"
|
||||
kdfSaltConstVMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce"
|
||||
kdfSaltConstVMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
|
||||
kdfSaltConstVMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length"
|
||||
)
|
||||
|
||||
func kdf(key []byte, path ...string) []byte {
|
||||
hmacCreator := &hMacCreator{value: []byte(kdfSaltConstVMessAEADKDF)}
|
||||
for _, v := range path {
|
||||
hmacCreator = &hMacCreator{value: []byte(v), parent: hmacCreator}
|
||||
}
|
||||
hmacf := hmacCreator.Create()
|
||||
hmacf.Write(key)
|
||||
return hmacf.Sum(nil)
|
||||
}
|
||||
|
||||
type hMacCreator struct {
|
||||
parent *hMacCreator
|
||||
value []byte
|
||||
}
|
||||
|
||||
func (h *hMacCreator) Create() hash.Hash {
|
||||
if h.parent == nil {
|
||||
return hmac.New(sha256.New, h.value)
|
||||
}
|
||||
return hmac.New(h.parent.Create, h.value)
|
||||
}
|
||||
|
||||
func createAuthID(cmdKey []byte, time int64) [16]byte {
|
||||
buf := &bytes.Buffer{}
|
||||
binary.Write(buf, binary.BigEndian, time)
|
||||
|
||||
random := make([]byte, 4)
|
||||
rand.Read(random)
|
||||
buf.Write(random)
|
||||
zero := crc32.ChecksumIEEE(buf.Bytes())
|
||||
binary.Write(buf, binary.BigEndian, zero)
|
||||
|
||||
aesBlock, _ := aes.NewCipher(kdf(cmdKey[:], kdfSaltConstAuthIDEncryptionKey)[:16])
|
||||
var result [16]byte
|
||||
aesBlock.Encrypt(result[:], buf.Bytes())
|
||||
return result
|
||||
}
|
||||
|
||||
func sealVMessAEADHeader(key [16]byte, data []byte, t time.Time) []byte {
|
||||
generatedAuthID := createAuthID(key[:], t.Unix())
|
||||
connectionNonce := make([]byte, 8)
|
||||
rand.Read(connectionNonce)
|
||||
|
||||
aeadPayloadLengthSerializedByte := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(aeadPayloadLengthSerializedByte, uint16(len(data)))
|
||||
|
||||
var payloadHeaderLengthAEADEncrypted []byte
|
||||
|
||||
{
|
||||
payloadHeaderLengthAEADKey := kdf(key[:], kdfSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))[:16]
|
||||
payloadHeaderLengthAEADNonce := kdf(key[:], kdfSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
payloadHeaderLengthAEADAESBlock, _ := aes.NewCipher(payloadHeaderLengthAEADKey)
|
||||
payloadHeaderAEAD, _ := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
|
||||
payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
|
||||
}
|
||||
|
||||
var payloadHeaderAEADEncrypted []byte
|
||||
|
||||
{
|
||||
payloadHeaderAEADKey := kdf(key[:], kdfSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))[:16]
|
||||
payloadHeaderAEADNonce := kdf(key[:], kdfSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
payloadHeaderAEADAESBlock, _ := aes.NewCipher(payloadHeaderAEADKey)
|
||||
payloadHeaderAEAD, _ := cipher.NewGCM(payloadHeaderAEADAESBlock)
|
||||
payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
|
||||
}
|
||||
|
||||
var outputBuffer = &bytes.Buffer{}
|
||||
|
||||
outputBuffer.Write(generatedAuthID[:])
|
||||
outputBuffer.Write(payloadHeaderLengthAEADEncrypted)
|
||||
outputBuffer.Write(connectionNonce)
|
||||
outputBuffer.Write(payloadHeaderAEADEncrypted)
|
||||
|
||||
return outputBuffer.Bytes()
|
||||
}
|
Reference in New Issue
Block a user