Skip to main content

Signed Packets

By default, the Secure Concentrator signs the LoRa packet payload and meteadata with its unique ED25519 Hardware Key. The Hardware Key is installed by the manufacturer and can not be changed. To optimize for low-latency, the unsigned data if first sent to the host CPU and the packet signature is later computed. This design allows the host CPU to serve latency-sensitive applications.

Signing data packets is performed by first converting the packet's metadata, payload, gps time, and location into a byte stream. The data is encoded using Borsh serialization. Please note: Borsh serializes the fields of a struct in the order they appear. For example, the RxPkt field will serialize freq first, then datarate, then snr, etc.

The nlighen loragw_hw


#[derive(Debug, Serialize, Deserialize)]
pub struct RxPkt {
/// Frequency in Hertz
pub freq: u32,
/// Datarate. Something like "SF7BW125"
pub datarate: String,
/// Signal to Noise radio (in 0.01 dB)
pub snr: i16,
/// Received Signal Strength Indicator (in 0.1 dBm)
pub rssi: i16,
/// 32 Mhz clock timestamp
pub tmst: u32,
/// Unique identifier of the Secure Concentrator.
pub card_id: [u8 ; 8],
// timestamp the packet was received (nanoseconds since the GPS epoch 1980-01-06 0:00 UTC)
pub gps_time: Option<u64>,
pub pos: Option<WGS84Position>,
pub payload: Vec<u8>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct WGS84Position {
/// longitude (deg) 1e-7 scale
pub lon: i32,

/// latitude (deg) 1e-7 scale
pub lat: i32,

/// Height above ellipsoid (millimeters)
pub height: i32,

/// Horizontal accuracy estimate (millimeters)
pub hacc: u32,

/// Vertical accuracy estimate (millimeters)
pub vacc: Option<u32>,
}

We have written Rust code to handle signing and verifying the RxPkt in the NLighten Core library.