package network import ( "errors" "fmt" "io" "net" "github.com/Andoryuuta/Erupe/network/crypto" ) // CryptConn represents a MHF encrypted two-way connection, // it automatically handles encryption, decryption, and key rotation via it's methods. type CryptConn struct { conn net.Conn readKeyRot uint32 sendKeyRot uint32 sentPackets int32 prevSendPacketCombinedCheck uint16 } // NewCryptConn creates a new CryptConn with proper default values. func NewCryptConn(conn net.Conn) *CryptConn { cc := &CryptConn{ conn: conn, readKeyRot: 995117, sendKeyRot: 995117, sentPackets: 0, prevSendPacketCombinedCheck: 0, } return cc } // ReadPacket reads an packet from the connection and returns the decrypted data. func (cc *CryptConn) ReadPacket() ([]byte, error) { // Read the raw 14 byte header. headerData := make([]byte, CryptPacketHeaderLength) _, err := io.ReadFull(cc.conn, headerData) if err != nil { return nil, err } //fmt.Printf("Header: %s\n", hex.Dump(headerData)) // Parse the data into a usable struct. cph, err := NewCryptPacketHeader(headerData) if err != nil { return nil, err } // Now read the encrypted packet body after getting its size from the header. encryptedPacketBody := make([]byte, cph.DataSize) _, err = io.ReadFull(cc.conn, encryptedPacketBody) if err != nil { return nil, err } // Update the key rotation before decrypting. if cph.KeyRotDelta != 0 { cc.readKeyRot = (uint32(cph.KeyRotDelta) * (cc.readKeyRot + 1)) } out, combinedCheck, check0, check1, check2 := crypto.Decrypt(encryptedPacketBody, cc.readKeyRot, nil) if cph.Check0 != check0 || cph.Check1 != check1 || cph.Check2 != check2 { fmt.Printf("got c0 %X, c1 %X, c2 %X\n", check0, check1, check2) fmt.Printf("want c0 %X, c1 %X, c2 %X\n", cph.Check0, cph.Check1, cph.Check2) return nil, errors.New("decrypted data checksum doesn't match header") } _ = combinedCheck /* fmt.Printf("cc %X, c0 %X, c1 %X, c2 %X\n", combinedCheck, check0, check1, check2) fmt.Printf("cc %X, c0 %X, c1 %X, c2 %X\n", cph.PrevPacketCombinedCheck, cph.Check0, cph.Check1, cph.Check2) fmt.Printf("cph: %+v\n", cph) */ return out, nil }