lux/net/lux_packet.go
2025-01-03 16:05:01 +02:00

87 lines
1.9 KiB
Go

package net
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"lux/crypto"
"lux/proto"
"net"
)
const LUX_PROTO_PACKET_HDRLEN = proto.LUX_PROTO_ID_SIZE + 2
type LuxPacket struct {
Target proto.LuxID
Type uint
Buffer proto.LuxBuffer
}
func DecryptLuxPacket(dgram LuxDatagram, key crypto.LuxKey) (LuxPacket, error) {
packet := LuxPacket{}
cipherBlock, err := aes.NewCipher(key.Key)
if err != nil {
return packet, err
}
decrypter := cipher.NewCBCDecrypter(cipherBlock, key.IV)
payloadLen := len(dgram.Payload)
if payloadLen == 0 || payloadLen%cipherBlock.BlockSize() != 0 {
return packet, errors.New("payload is not block aligned")
}
payload := make([]byte, payloadLen)
decrypter.CryptBlocks(payload, dgram.Payload)
packet.Buffer = proto.FromSlice(payload)
if err := packet.Target.Read(&packet.Buffer); err != nil {
return packet, err
}
if pType, err := packet.Buffer.ReadUint16(); err == nil {
packet.Type = uint(pType)
} else {
return packet, err
}
return packet, nil
}
func EncryptLuxPacket(packet LuxPacket, key crypto.LuxKey, target *net.UDPAddr) (LuxDatagram, error) {
dgram := LuxDatagram{}
cipherBlock, err := aes.NewCipher(key.Key)
if err != nil {
return dgram, err
}
encrypter := cipher.NewCBCEncrypter(cipherBlock, key.IV)
var paddingLen int
packetLen := packet.Buffer.Length()
if packetLen%encrypter.BlockSize() != 0 {
paddingLen = ((packetLen / encrypter.BlockSize()) + 1) * encrypter.BlockSize()
} else {
paddingLen = 0
}
padding := make([]byte, paddingLen)
_, err = rand.Read(padding)
if err != nil {
return dgram, err
}
wd := proto.AllocLuxBuffer(LUX_PROTO_PACKET_HDRLEN + packetLen + paddingLen)
key.Id.Write(&wd)
wd.WriteUint16(uint16(packet.Type))
wd.WriteBytes(packet.Buffer.AllBytes())
wd.WriteBytes(padding)
dgram.Target = target
dgram.Payload = make([]byte, wd.Length())
encrypter.CryptBlocks(dgram.Payload, wd.AllBytes())
return dgram, nil
}