123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- 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[:])
- }
- outputBuffer := &bytes.Buffer{}
- outputBuffer.Write(generatedAuthID[:])
- outputBuffer.Write(payloadHeaderLengthAEADEncrypted)
- outputBuffer.Write(connectionNonce)
- outputBuffer.Write(payloadHeaderAEADEncrypted)
- return outputBuffer.Bytes()
- }
|