Mining/pkg/ueps/packet.go
Claude b0a39b9c71
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run
ax(ueps): replace errors.Is usage example with direct equality check
Comment was teaching agents to use the banned errors package.
Direct sentinel comparison (err == errTLVValueTooLarge) is correct.

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

128 lines
4.1 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 // semantic token identifying the packet's purpose
ThreatScore uint16 // 065535; elevated by integrity violations
}
// builder := ueps.NewBuilder(intentID, payload); frame, _ := builder.MarshalAndSign(secret)
type PacketBuilder struct {
Header UEPSHeader
Payload []byte
}
// builder := ueps.NewBuilder(0x01, []byte("hello"))
// builder.Header.ThreatScore = 100
// frame, err := builder.MarshalAndSign(sharedSecret)
func NewBuilder(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)
// 1. Write Standard Header Tags (0x01 - 0x05)
// We write these first because they are part of what we sign.
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
}
// Threat Score is uint16, needs binary packing
threatScoreBytes := make([]byte, 2)
binary.BigEndian.PutUint16(threatScoreBytes, builder.Header.ThreatScore)
if err := writeTLV(buffer, TagThreatScore, threatScoreBytes); err != nil {
return nil, err
}
// 2. Calculate HMAC
// The signature covers: Existing Header TLVs + The Payload
// It does NOT cover the HMAC TLV tag itself (obviously)
messageAuthCode := hmac.New(sha256.New, sharedSecret)
messageAuthCode.Write(buffer.Bytes()) // The headers so far
messageAuthCode.Write(builder.Payload) // The data
signature := messageAuthCode.Sum(nil)
// 3. Write HMAC TLV (0x06)
// Length is 32 bytes for SHA256
if err := writeTLV(buffer, TagHMAC, signature); err != nil {
return nil, err
}
// 4. Write Payload TLV (0xFF) — tag byte only; payload appended length-prefixless.
// 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
}