Mining/pkg/ueps/packet.go
Claude 3d310faec7
ax(ueps): replace prose comments with usage examples in MarshalAndSign
Numbered step comments ("2. Calculate HMAC", "3. Write HMAC TLV") and
inline narration violated AX Principle 2 — comments must show concrete
usage, not restate what the code already says.

Co-Authored-By: Charon <charon@lethean.io>
2026-04-02 09:58:02 +01:00

123 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ueps
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/binary"
"io"
)
// writeTLV(buffer, TagPayload, oversized) → errTLVValueTooLarge
// if err == errTLVValueTooLarge { /* value exceeded 255-byte TLV length limit */ }
var errTLVValueTooLarge = tlvError("TLV value too large for 1-byte length header")
// var errMyError = tlvError("my error message")
type tlvError string
func (e tlvError) Error() string { return string(e) }
// TLV Types
const (
TagVersion = 0x01
TagCurrentLayer = 0x02
TagTargetLayer = 0x03
TagIntent = 0x04
TagThreatScore = 0x05
TagHMAC = 0x06 // writeTLV(buffer, TagHMAC, hmacSignature) — covers all preceding header TLVs + payload
TagPayload = 0xFF // buffer.WriteByte(TagPayload); buffer.Write(rawPayload) — no length prefix
)
// header := ueps.UEPSHeader{Version: 0x09, CurrentLayer: 5, TargetLayer: 3, IntentID: 0x01, ThreatScore: 0}
type UEPSHeader struct {
Version uint8 // 0x09 = IPv9
CurrentLayer uint8 // OSI layer of the sender (5 = Application)
TargetLayer uint8 // OSI layer of the destination
IntentID uint8 // header.IntentID = 0x01 (ping), 0x02 (data), 0x03 (auth)
ThreatScore uint16 // 065535; elevated by integrity violations
}
// builder := ueps.NewPacketBuilder(intentID, payload); frame, _ := builder.MarshalAndSign(secret)
type PacketBuilder struct {
Header UEPSHeader
Payload []byte
}
// builder := ueps.NewPacketBuilder(0x01, []byte("hello"))
// builder.Header.ThreatScore = 100
// frame, err := builder.MarshalAndSign(sharedSecret)
func NewPacketBuilder(intentID uint8, payload []byte) *PacketBuilder {
return &PacketBuilder{
Header: UEPSHeader{
Version: 0x09, // IPv9
CurrentLayer: 5, // Application
TargetLayer: 5, // Application
IntentID: intentID,
ThreatScore: 0, // Assumed innocent until proven guilty
},
Payload: payload,
}
}
// frame, err := builder.MarshalAndSign([]byte("my-shared-secret"))
func (builder *PacketBuilder) MarshalAndSign(sharedSecret []byte) ([]byte, error) {
buffer := new(bytes.Buffer)
// writeTLV(buffer, TagVersion, []byte{builder.Header.Version}) → [0x01, 0x01, 0x09]
if err := writeTLV(buffer, TagVersion, []byte{builder.Header.Version}); err != nil {
return nil, err
}
if err := writeTLV(buffer, TagCurrentLayer, []byte{builder.Header.CurrentLayer}); err != nil {
return nil, err
}
if err := writeTLV(buffer, TagTargetLayer, []byte{builder.Header.TargetLayer}); err != nil {
return nil, err
}
if err := writeTLV(buffer, TagIntent, []byte{builder.Header.IntentID}); err != nil {
return nil, err
}
// binary.BigEndian.PutUint16(threatScoreBytes, 100) → [0x00, 0x64]
threatScoreBytes := make([]byte, 2)
binary.BigEndian.PutUint16(threatScoreBytes, builder.Header.ThreatScore)
if err := writeTLV(buffer, TagThreatScore, threatScoreBytes); err != nil {
return nil, err
}
// messageAuthCode.Write(buffer.Bytes()) → covers all header TLVs before the HMAC tag
messageAuthCode := hmac.New(sha256.New, sharedSecret)
messageAuthCode.Write(buffer.Bytes())
messageAuthCode.Write(builder.Payload)
signature := messageAuthCode.Sum(nil)
// writeTLV(buffer, TagHMAC, signature) → [0x06, 0x20, <32 bytes>]
if err := writeTLV(buffer, TagHMAC, signature); err != nil {
return nil, err
}
// buffer.Bytes() → [...headerTLVs..., 0x06, 0x20, <hmac32>, 0xFF, <payload...>]
buffer.WriteByte(TagPayload)
buffer.Write(builder.Payload)
return buffer.Bytes(), nil
}
// writeTLV(buffer, TagVersion, []byte{0x09})
// writeTLV(buffer, TagIntent, []byte{intentID})
func writeTLV(writer io.Writer, tag uint8, value []byte) error {
// Check strict length constraint (1 byte length = max 255 bytes)
if len(value) > 255 {
return errTLVValueTooLarge
}
if _, err := writer.Write([]byte{tag}); err != nil {
return err
}
if _, err := writer.Write([]byte{uint8(len(value))}); err != nil {
return err
}
if _, err := writer.Write(value); err != nil {
return err
}
return nil
}