Mining/pkg/ueps/reader.go
Claude 092aaf4870
ax(ueps): rename tagLengthByte/tagLength to tagValueLength
AX Principle 1 — the `Byte` suffix encodes storage type not semantics,
and the intermediate `tagLength` variable was an immediate int cast of
`tagLengthByte` with no additional meaning. Collapsed to a single
`tagValueLength` variable that names what it is, not how it is stored.

Co-Authored-By: Charon <charon@lethean.io>
2026-04-02 10:25:39 +01:00

113 lines
3.1 KiB
Go

package ueps
import (
"bufio"
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/binary"
"io"
)
// packet, err := ReadAndVerify(bufio.NewReader(conn), secret)
// if err == errMissingHMAC { /* no HMAC tag found in frame */ }
var errMissingHMAC = tlvError("UEPS packet missing HMAC signature")
// packet, err := ReadAndVerify(bufio.NewReader(conn), wrongSecret)
// if err == errIntegrityViolation { /* HMAC mismatch — threat score incremented */ }
var errIntegrityViolation = tlvError("integrity violation: HMAC mismatch (ThreatScore +100)")
// packet, err := ueps.ReadAndVerify(bufio.NewReader(conn), sharedSecret)
// if err == nil { _ = packet.Header.IntentID; _ = packet.Header.ThreatScore; _ = packet.Payload }
type ParsedPacket struct {
Header UEPSHeader
Payload []byte
}
// packet, err := ueps.ReadAndVerify(bufio.NewReader(conn), []byte("my-shared-secret"))
// if err == nil { dispatch(packet.Header.IntentID, packet.Header.ThreatScore, packet.Payload) }
func ReadAndVerify(reader *bufio.Reader, sharedSecret []byte) (*ParsedPacket, error) {
var signedData bytes.Buffer
header := UEPSHeader{}
var hmacSignature []byte
var payload []byte
for {
tagByte, err := reader.ReadByte()
if err != nil {
return nil, err
}
if tagByte == TagPayload {
var err error
payload, err = io.ReadAll(reader)
if err != nil {
return nil, err
}
break
}
tagValueLength, err := reader.ReadByte()
if err != nil {
return nil, err
}
tagValue := make([]byte, tagValueLength)
if _, err := io.ReadFull(reader, tagValue); err != nil {
return nil, err
}
switch tagByte {
case TagVersion:
header.Version = tagValue[0]
signedData.WriteByte(tagByte)
signedData.WriteByte(tagValueLength)
signedData.Write(tagValue)
case TagCurrentLayer:
header.CurrentLayer = tagValue[0]
signedData.WriteByte(tagByte)
signedData.WriteByte(tagValueLength)
signedData.Write(tagValue)
case TagTargetLayer:
header.TargetLayer = tagValue[0]
signedData.WriteByte(tagByte)
signedData.WriteByte(tagValueLength)
signedData.Write(tagValue)
case TagIntent:
header.IntentID = tagValue[0]
signedData.WriteByte(tagByte)
signedData.WriteByte(tagValueLength)
signedData.Write(tagValue)
case TagThreatScore:
header.ThreatScore = binary.BigEndian.Uint16(tagValue)
signedData.WriteByte(tagByte)
signedData.WriteByte(tagValueLength)
signedData.Write(tagValue)
case TagHMAC:
hmacSignature = tagValue
default:
// signedData.WriteByte(unknownTag); signedData.Write(tagValue) — unknown tags contribute to HMAC, blocking injection
signedData.WriteByte(tagByte)
signedData.WriteByte(tagValueLength)
signedData.Write(tagValue)
}
}
if len(hmacSignature) == 0 {
return nil, errMissingHMAC
}
messageAuthCode := hmac.New(sha256.New, sharedSecret)
messageAuthCode.Write(signedData.Bytes())
messageAuthCode.Write(payload)
expectedMessageAuthCode := messageAuthCode.Sum(nil)
if !hmac.Equal(hmacSignature, expectedMessageAuthCode) {
return nil, errIntegrityViolation
}
return &ParsedPacket{
Header: header,
Payload: payload,
}, nil
}