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.