func (v *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) { timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)() account, err := header.User.GetTypedAccount() if err != nil { log.Error("VMess: Failed to get user account: ", err) return } idHash := v.idHash(account.(*vmess.InternalAccount).AnyValidID().Bytes()) idHash.Write(timestamp.Bytes(nil)) writer.Write(idHash.Sum(nil)) buffer := make([]byte, 0, 512) buffer = append(buffer, Version) buffer = append(buffer, v.requestBodyIV...) buffer = append(buffer, v.requestBodyKey...) buffer = append(buffer, v.responseHeader, byte(header.Option)) padingLen := dice.Roll(16) if header.Security.Is(protocol.SecurityType_LEGACY) { // Disable padding in legacy mode for a smooth transition. padingLen = 0 } security := byte(padingLen<<4) | byte(header.Security) buffer = append(buffer, security, byte(0), byte(header.Command)) buffer = header.Port.Bytes(buffer) switch header.Address.Family() { case v2net.AddressFamilyIPv4: buffer = append(buffer, AddrTypeIPv4) buffer = append(buffer, header.Address.IP()...) case v2net.AddressFamilyIPv6: buffer = append(buffer, AddrTypeIPv6) buffer = append(buffer, header.Address.IP()...) case v2net.AddressFamilyDomain: buffer = append(buffer, AddrTypeDomain, byte(len(header.Address.Domain()))) buffer = append(buffer, header.Address.Domain()...) } if padingLen > 0 { pading := make([]byte, padingLen) rand.Read(pading) buffer = append(buffer, pading...) } fnv1a := fnv.New32a() fnv1a.Write(buffer) buffer = fnv1a.Sum(buffer) timestampHash := md5.New() timestampHash.Write(hashTimestamp(timestamp)) iv := timestampHash.Sum(nil) aesStream := crypto.NewAesEncryptionStream(account.(*vmess.InternalAccount).ID.CmdKey(), iv) aesStream.XORKeyStream(buffer, buffer) writer.Write(buffer) return }
func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer { var authWriter io.Writer if request.Security.Is(protocol.SecurityType_NONE) { if request.Option.Has(protocol.RequestOptionChunkStream) { auth := &crypto.AEADAuthenticator{ AEAD: new(FnvAuthenticator), NonceGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, writer) } else { authWriter = writer } } else if request.Security.Is(protocol.SecurityType_LEGACY) { aesStream := crypto.NewAesEncryptionStream(v.requestBodyKey, v.requestBodyIV) cryptionWriter := crypto.NewCryptionWriter(aesStream, writer) if request.Option.Has(protocol.RequestOptionChunkStream) { auth := &crypto.AEADAuthenticator{ AEAD: new(FnvAuthenticator), NonceGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, cryptionWriter) } else { authWriter = cryptionWriter } } else if request.Security.Is(protocol.SecurityType_AES128_GCM) { block, _ := aes.NewCipher(v.requestBodyKey) aead, _ := cipher.NewGCM(block) auth := &crypto.AEADAuthenticator{ AEAD: aead, NonceGenerator: &ChunkNonceGenerator{ Nonce: append([]byte(nil), v.requestBodyIV...), Size: aead.NonceSize(), }, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, writer) } else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) { aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.requestBodyKey)) auth := &crypto.AEADAuthenticator{ AEAD: aead, NonceGenerator: &ChunkNonceGenerator{ Nonce: append([]byte(nil), v.requestBodyIV...), Size: aead.NonceSize(), }, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, writer) } return buf.NewWriter(authWriter) }
func (this *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) { responseBodyKey := md5.Sum(this.requestBodyKey) responseBodyIV := md5.Sum(this.requestBodyIV) this.responseBodyKey = responseBodyKey[:] this.responseBodyIV = responseBodyIV[:] aesStream := crypto.NewAesEncryptionStream(this.responseBodyKey, this.responseBodyIV) encryptionWriter := crypto.NewCryptionWriter(aesStream, writer) this.responseWriter = encryptionWriter encryptionWriter.Write([]byte{this.responseHeader, byte(header.Option)}) err := MarshalCommand(header.Command, encryptionWriter) if err != nil { encryptionWriter.Write([]byte{0x00, 0x00}) } }
func (this *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) { timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)() account, err := header.User.GetTypedAccount() if err != nil { log.Error("VMess: Failed to get user account: ", err) return } idHash := this.idHash(account.(*vmess.InternalAccount).AnyValidID().Bytes()) idHash.Write(timestamp.Bytes(nil)) writer.Write(idHash.Sum(nil)) buffer := make([]byte, 0, 512) buffer = append(buffer, Version) buffer = append(buffer, this.requestBodyIV...) buffer = append(buffer, this.requestBodyKey...) buffer = append(buffer, this.responseHeader, byte(header.Option), byte(0), byte(0), byte(header.Command)) buffer = header.Port.Bytes(buffer) switch header.Address.Family() { case v2net.AddressFamilyIPv4: buffer = append(buffer, AddrTypeIPv4) buffer = append(buffer, header.Address.IP()...) case v2net.AddressFamilyIPv6: buffer = append(buffer, AddrTypeIPv6) buffer = append(buffer, header.Address.IP()...) case v2net.AddressFamilyDomain: buffer = append(buffer, AddrTypeDomain, byte(len(header.Address.Domain()))) buffer = append(buffer, header.Address.Domain()...) } fnv1a := fnv.New32a() fnv1a.Write(buffer) buffer = fnv1a.Sum(buffer) timestampHash := md5.New() timestampHash.Write(hashTimestamp(timestamp)) iv := timestampHash.Sum(nil) aesStream := crypto.NewAesEncryptionStream(account.(*vmess.InternalAccount).ID.CmdKey(), iv) aesStream.XORKeyStream(buffer, buffer) writer.Write(buffer) return }
func (this *ClientSession) EncodeRequestBody(writer io.Writer) io.Writer { aesStream := crypto.NewAesEncryptionStream(this.requestBodyKey, this.requestBodyIV) return crypto.NewCryptionWriter(aesStream, writer) }
func (v *AesCfb) NewEncodingStream(key []byte, iv []byte) (cipher.Stream, error) { stream := crypto.NewAesEncryptionStream(key, iv) return stream, nil }