From 79e1caa815e6bf607cf6f6a45234c50f47748091 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sat, 4 Jan 2025 18:20:36 -0600 Subject: [PATCH] 0.3.7 - announce packet improvements, cryptgraphy pkg, cleanup --- pkg/announce/announce.go | 91 +++++++++++++------------------------ pkg/announce/handler.go | 2 + pkg/interfaces/interface.go | 28 ++++++++++++ pkg/link/link.go | 48 ++++++++++++------- pkg/packet/constants.go | 8 ++-- pkg/packet/packet.go | 2 +- pkg/transport/transport.go | 52 ++++++++++++++++----- 7 files changed, 137 insertions(+), 94 deletions(-) diff --git a/pkg/announce/announce.go b/pkg/announce/announce.go index e7f66be..3503f45 100644 --- a/pkg/announce/announce.go +++ b/pkg/announce/announce.go @@ -169,7 +169,7 @@ func (a *Announce) HandleAnnounce(data []byte) error { log.Printf("[DEBUG-7] Handling announce packet of %d bytes", len(data)) - // Minimum packet size validation (header(2) + desthash(16) + enckey(32) + signkey(32) + namehash(10) + + // Minimum packet size validation (header(2) + desthash(16) + enckey(32) + signkey(32) + namehash(10) + // randomhash(10) + signature(64) + min app data(3)) if len(data) < 169 { log.Printf("[DEBUG-7] Invalid announce data length: %d bytes", len(data)) @@ -187,7 +187,7 @@ func (a *Announce) HandleAnnounce(data []byte) error { signature := data[102:166] appData := data[166:] - log.Printf("[DEBUG-7] Announce fields: destHash=%x, encKey=%x, signKey=%x", + log.Printf("[DEBUG-7] Announce fields: destHash=%x, encKey=%x, signKey=%x", destHash, encKey, signKey) log.Printf("[DEBUG-7] Name hash=%x, random hash=%x", nameHash, randomHash) @@ -254,83 +254,54 @@ func CreateHeader(ifacFlag byte, headerType byte, contextFlag byte, propType byt } func (a *Announce) CreatePacket() []byte { - log.Printf("[DEBUG-7] Creating announce packet") - - // Create header byte - headerByte := byte( - (IFAC_NONE) | // No interface auth - (HEADER_TYPE_1 << 6) | // Single address field - (0 << 5) | // No context - (PROP_TYPE_BROADCAST << 4) | // Broadcast propagation - (DEST_TYPE_SINGLE << 2) | // Single destination - PACKET_TYPE_ANNOUNCE, // Announce packet type + // Create header + header := CreateHeader( + IFAC_NONE, + HEADER_TYPE_1, + 0, // No context flag + PROP_TYPE_BROADCAST, + DEST_TYPE_SINGLE, + PACKET_TYPE_ANNOUNCE, + a.hops, ) - log.Printf("[DEBUG-7] Created header byte: %02x, hops: %d", headerByte, a.hops) - packet := []byte{headerByte, a.hops} + packet := header // Add destination hash (16 bytes) - log.Printf("[DEBUG-7] Adding destination hash (16 bytes): %x", a.destinationHash) packet = append(packet, a.destinationHash...) - // Get full public key and split into encryption and signing keys + // Add public key parts (32 bytes each) pubKey := a.identity.GetPublicKey() - encKey := pubKey[:32] // x25519 public key for encryption - signKey := pubKey[32:] // Ed25519 public key for signing - - // Add encryption key (32 bytes) - log.Printf("[DEBUG-7] Adding encryption key (32 bytes): %x", encKey) - packet = append(packet, encKey...) - - // Add signing key (32 bytes) - log.Printf("[DEBUG-7] Adding signing key (32 bytes): %x", signKey) - packet = append(packet, signKey...) + packet = append(packet, pubKey[:32]...) // Encryption key + packet = append(packet, pubKey[32:]...) // Signing key // Add name hash (10 bytes) nameHash := sha256.Sum256([]byte(fmt.Sprintf("%s.%s", a.config.AppName, a.config.AppAspect))) - log.Printf("[DEBUG-7] Adding name hash (10 bytes): %x", nameHash[:10]) packet = append(packet, nameHash[:10]...) - // Add random hash (10 bytes: 5 random + 5 timestamp) - randomBytes := make([]byte, 5) + // Add random hash (10 bytes) + randomBytes := make([]byte, 10) rand.Read(randomBytes) - timeBytes := make([]byte, 8) - binary.BigEndian.PutUint64(timeBytes, uint64(time.Now().Unix())) - log.Printf("[DEBUG-7] Adding random hash (10 bytes): %x%x", randomBytes, timeBytes[:5]) packet = append(packet, randomBytes...) - packet = append(packet, timeBytes[:5]...) - // Add ratchet ID if present (32 bytes) - if a.ratchetID != nil { - log.Printf("[DEBUG-7] Adding ratchet ID (32 bytes): %x", a.ratchetID) - packet = append(packet, a.ratchetID...) - } + // Create validation data for signature + validationData := make([]byte, 0) + validationData = append(validationData, a.destinationHash...) + validationData = append(validationData, pubKey[:32]...) // Encryption key + validationData = append(validationData, pubKey[32:]...) // Signing key + validationData = append(validationData, nameHash[:10]...) + validationData = append(validationData, randomBytes...) + validationData = append(validationData, a.appData...) - // Create msgpack array for app data - appData := []byte{ - 0x92, // msgpack array of 2 elements - 0xc4, // bin 8 format for byte array - } - - // Add name bytes - nameBytes := []byte(fmt.Sprintf("%s.%s", a.config.AppName, a.config.AppAspect)) - appData = append(appData, byte(len(nameBytes))) // length prefix - appData = append(appData, nameBytes...) // name bytes - appData = append(appData, 0x00) // ticket value = 0 - - // Create signature over destination hash and app data - signData := append(a.destinationHash, appData...) - if a.ratchetID != nil { - signData = append(signData, a.ratchetID...) - } - signature := a.identity.Sign(signData) - log.Printf("[DEBUG-7] Adding signature (64 bytes): %x", signature) + // Add signature (64 bytes) + signature := a.identity.Sign(validationData) packet = append(packet, signature...) - // Finally add the app data - packet = append(packet, appData...) + // Add app data + if len(a.appData) > 0 { + packet = append(packet, a.appData...) + } - log.Printf("[DEBUG-7] Final packet size: %d bytes", len(packet)) return packet } diff --git a/pkg/announce/handler.go b/pkg/announce/handler.go index a5e03a9..b9e6beb 100644 --- a/pkg/announce/handler.go +++ b/pkg/announce/handler.go @@ -1,5 +1,7 @@ package announce type Handler interface { + AspectFilter() []string ReceivedAnnounce(destHash []byte, identity interface{}, appData []byte) error + ReceivePathResponses() bool } diff --git a/pkg/interfaces/interface.go b/pkg/interfaces/interface.go index 186bdc7..0993f9f 100644 --- a/pkg/interfaces/interface.go +++ b/pkg/interfaces/interface.go @@ -284,3 +284,31 @@ func (i *BaseInterface) updateBandwidthStats(bytes uint64) { log.Printf("[DEBUG-%d] Interface %s: Updated bandwidth stats - TX bytes: %d, Last TX: %v", DEBUG_LEVEL, i.Name, i.TxBytes, i.lastTx) } + +type InterceptedInterface struct { + Interface + interceptor func([]byte, common.NetworkInterface) error + originalSend func([]byte, string) error +} + +// Create constructor for intercepted interface +func NewInterceptedInterface(base Interface, interceptor func([]byte, common.NetworkInterface) error) *InterceptedInterface { + return &InterceptedInterface{ + Interface: base, + interceptor: interceptor, + originalSend: base.Send, + } +} + +// Implement Send method for intercepted interface +func (i *InterceptedInterface) Send(data []byte, addr string) error { + // Call interceptor if provided + if i.interceptor != nil && len(data) > 0 { + if err := i.interceptor(data, i); err != nil { + log.Printf("[DEBUG-2] Failed to intercept outgoing packet: %v", err) + } + } + + // Call original send + return i.originalSend(data, addr) +} diff --git a/pkg/link/link.go b/pkg/link/link.go index a91bf81..8efcfd5 100644 --- a/pkg/link/link.go +++ b/pkg/link/link.go @@ -13,6 +13,7 @@ import ( "sync" "time" + "github.com/Sudo-Ivan/reticulum-go/pkg/common" "github.com/Sudo-Ivan/reticulum-go/pkg/destination" "github.com/Sudo-Ivan/reticulum-go/pkg/identity" "github.com/Sudo-Ivan/reticulum-go/pkg/packet" @@ -52,6 +53,7 @@ type Link struct { mutex sync.RWMutex destination *destination.Destination status byte + networkInterface common.NetworkInterface establishedAt time.Time lastInbound time.Time lastOutbound time.Time @@ -94,11 +96,12 @@ type Link struct { initiator bool } -func NewLink(dest *destination.Destination, transport *transport.Transport, establishedCallback func(*Link), closedCallback func(*Link)) *Link { +func NewLink(dest *destination.Destination, transport *transport.Transport, networkIface common.NetworkInterface, establishedCallback func(*Link), closedCallback func(*Link)) *Link { return &Link{ destination: dest, status: STATUS_PENDING, transport: transport, + networkInterface: networkIface, establishedCallback: establishedCallback, closedCallback: closedCallback, establishedAt: time.Time{}, // Zero time until established @@ -775,25 +778,36 @@ func (l *Link) decodePacket(data []byte) { } case packet.PacketTypeAnnounce: - log.Printf("[DEBUG-7] - Type Description: RNS Announce") - if len(data) > 33 { - destHash := data[1:17] - pubKey := data[17:49] - log.Printf("[DEBUG-7] - Destination Hash: %x", destHash) - log.Printf("[DEBUG-7] - Public Key: %x", pubKey) + log.Printf("[DEBUG-7] Received announce packet (%d bytes)", len(data)) + if len(data) < packet.MinAnnounceSize { + log.Printf("[DEBUG-3] Announce packet too short: %d bytes", len(data)) + return + } - if len(data) > 81 { - signature := data[49:81] - appData := data[81:] - if identity.ValidateAnnounce(data, destHash, pubKey, signature, appData) { - log.Printf("[DEBUG-7] - Announce signature valid") + destHash := data[2:18] + encKey := data[18:50] + signKey := data[50:82] + nameHash := data[82:92] + randomHash := data[92:102] + signature := data[102:166] + appData := data[166:] - if path, ok := l.pathFinder.GetPath(hex.EncodeToString(destHash)); ok { - log.Printf("[DEBUG-7] - Updated path: Interface=%s, Hops=%d", - path.Interface, path.HopCount) - } - } + pubKey := append(encKey, signKey...) + + validationData := make([]byte, 0, 164) + validationData = append(validationData, destHash...) + validationData = append(validationData, encKey...) + validationData = append(validationData, signKey...) + validationData = append(validationData, nameHash...) + validationData = append(validationData, randomHash...) + + if identity.ValidateAnnounce(validationData, destHash, pubKey, signature, appData) { + log.Printf("[DEBUG-4] Valid announce from %x", pubKey[:8]) + if err := l.transport.HandleAnnounce(destHash, l.networkInterface); err != nil { + log.Printf("[DEBUG-3] Failed to handle announce: %v", err) } + } else { + log.Printf("[DEBUG-3] Invalid announce signature from %x", pubKey[:8]) } case packet.PacketTypeProof: diff --git a/pkg/packet/constants.go b/pkg/packet/constants.go index ed9206f..ba5c0be 100644 --- a/pkg/packet/constants.go +++ b/pkg/packet/constants.go @@ -15,9 +15,7 @@ const ( DestinationPlain = 2 DestinationLink = 3 - // Packet Types - PacketData = 0 - PacketAnnounce = 1 - PacketLinkRequest = 2 - PacketProof = 3 + // Minimum packet sizes + MinAnnounceSize = 169 // header(2) + desthash(16) + enckey(32) + signkey(32) + + // namehash(10) + randomhash(10) + signature(64) + min appdata(3) ) diff --git a/pkg/packet/packet.go b/pkg/packet/packet.go index 0fcc08f..fb460b8 100644 --- a/pkg/packet/packet.go +++ b/pkg/packet/packet.go @@ -82,7 +82,7 @@ type Packet struct { SNR *float64 Q *float64 - Addresses []byte // Add this field for address storage + Addresses []byte } func NewPacket(destType byte, data []byte, packetType byte, context byte, diff --git a/pkg/transport/transport.go b/pkg/transport/transport.go index 7f2496d..6cd45b3 100644 --- a/pkg/transport/transport.go +++ b/pkg/transport/transport.go @@ -1041,7 +1041,9 @@ func (l *Link) GetStatus() int { func CreateAnnouncePacket(destHash []byte, identity *identity.Identity, appData []byte, hops byte, config *common.ReticulumConfig) []byte { log.Printf("[DEBUG-7] Creating announce packet") + log.Printf("[DEBUG-7] Input parameters: destHash=%x, appData=%x, hops=%d", destHash, appData, hops) + // Create header (2 bytes) headerByte := byte( (0 << 7) | // Interface flag (IFAC_NONE) (0 << 6) | // Header type (HEADER_TYPE_1) @@ -1051,32 +1053,42 @@ func CreateAnnouncePacket(destHash []byte, identity *identity.Identity, appData PACKET_TYPE_ANNOUNCE, // Packet type (0x01) ) - log.Printf("[DEBUG-7] Created header byte: %02x, hops: %d", headerByte, hops) + log.Printf("[DEBUG-7] Created header byte: 0x%02x, hops: %d", headerByte, hops) packet := []byte{headerByte, hops} + log.Printf("[DEBUG-7] Initial packet size: %d bytes", len(packet)) // Add destination hash (16 bytes) + if len(destHash) > 16 { + destHash = destHash[:16] + } log.Printf("[DEBUG-7] Adding destination hash (16 bytes): %x", destHash) packet = append(packet, destHash...) + log.Printf("[DEBUG-7] Packet size after adding destination hash: %d bytes", len(packet)) // Get full public key and split into encryption and signing keys pubKey := identity.GetPublicKey() encKey := pubKey[:32] // x25519 public key for encryption signKey := pubKey[32:] // Ed25519 public key for signing + log.Printf("[DEBUG-7] Full public key: %x", pubKey) // Add encryption key (32 bytes) log.Printf("[DEBUG-7] Adding encryption key (32 bytes): %x", encKey) packet = append(packet, encKey...) + log.Printf("[DEBUG-7] Packet size after adding encryption key: %d bytes", len(packet)) // Add signing key (32 bytes) log.Printf("[DEBUG-7] Adding signing key (32 bytes): %x", signKey) packet = append(packet, signKey...) + log.Printf("[DEBUG-7] Packet size after adding signing key: %d bytes", len(packet)) // Add name hash (10 bytes) - nameHash := sha256.Sum256([]byte(fmt.Sprintf("%s.%s", config.AppName, config.AppAspect))) + nameString := fmt.Sprintf("%s.%s", config.AppName, config.AppAspect) + nameHash := sha256.Sum256([]byte(nameString)) log.Printf("[DEBUG-7] Adding name hash (10 bytes): %x", nameHash[:10]) packet = append(packet, nameHash[:10]...) + log.Printf("[DEBUG-7] Packet size after adding name hash: %d bytes", len(packet)) - // Add random hash (5 random + 5 timestamp bytes = 10 bytes) + // Add random hash (10 bytes) randomBytes := make([]byte, 5) rand.Read(randomBytes) timeBytes := make([]byte, 8) @@ -1084,16 +1096,20 @@ func CreateAnnouncePacket(destHash []byte, identity *identity.Identity, appData log.Printf("[DEBUG-7] Adding random hash (10 bytes): %x%x", randomBytes, timeBytes[:5]) packet = append(packet, randomBytes...) packet = append(packet, timeBytes[:5]...) + log.Printf("[DEBUG-7] Packet size after adding random hash: %d bytes", len(packet)) // Create msgpack array for app data - nameBytes := []byte(fmt.Sprintf("%s.%s", config.AppName, config.AppAspect)) - appDataMsg := []byte{ - 0x92, // msgpack array of 2 elements - 0xc4, // bin 8 format for byte array - byte(len(nameBytes)), // length prefix - } - log.Printf("[DEBUG-7] Adding name bytes: %x", nameBytes) + nameBytes := []byte(nameString) + appDataMsg := []byte{0x92} // array of 2 elements + + // Add name as first element + appDataMsg = append(appDataMsg, 0xc4) // bin 8 format + appDataMsg = append(appDataMsg, byte(len(nameBytes))) // length appDataMsg = append(appDataMsg, nameBytes...) + + // Add app data as second element + appDataMsg = append(appDataMsg, 0xc4) // bin 8 format + appDataMsg = append(appDataMsg, byte(len(appData))) // length appDataMsg = append(appDataMsg, appData...) // Create signature over destination hash and app data @@ -1101,10 +1117,24 @@ func CreateAnnouncePacket(destHash []byte, identity *identity.Identity, appData signature := identity.Sign(signData) log.Printf("[DEBUG-7] Adding signature (64 bytes): %x", signature) packet = append(packet, signature...) + log.Printf("[DEBUG-7] Packet size after adding signature: %d bytes", len(packet)) // Finally add the app data message packet = append(packet, appDataMsg...) - log.Printf("[DEBUG-7] Final packet size: %d bytes", len(packet)) + log.Printf("[DEBUG-7] Complete packet: %x", packet) + return packet } + +func (t *Transport) GetInterfaces() map[string]common.NetworkInterface { + t.mutex.RLock() + defer t.mutex.RUnlock() + + interfaces := make(map[string]common.NetworkInterface, len(t.interfaces)) + for k, v := range t.interfaces { + interfaces[k] = v + } + + return interfaces +}