LoRa and LoRaWAN
- LoRa and LoRaWAN
Why this matters
LoRa is the course’s main radio target, and it earns that position for a teaching reason as much as a practical one: you can see the modulation. A waterfall plot of LoRa traffic shows unmistakable diagonal sweeps. Concepts that are abstract in every other protocol — spreading, processing gain, the trade between data rate and range — are visible on screen.
It is also the cleanest illustration in the course of a distinction students routinely get wrong, and which determines every security property that follows:
LoRa is a physical layer with no security whatsoever. LoRaWAN is the MAC layer that adds it. They are not the same thing and the difference is not pedantic.
The radio layer
Chirp spread spectrum
LoRa encodes symbols as chirps — signals that sweep linearly across the channel bandwidth. A symbol’s value is encoded in where the sweep starts; it wraps around the band and continues, so every symbol occupies the full bandwidth for its full duration.
This is spread spectrum, and it buys processing gain: the receiver correlates against the known chirp shape, which concentrates the signal and disperses the noise. LoRa demodulates reliably at signal levels below the noise floor — down to about −137 dBm at the slowest settings. That is the whole trick, and it is why a 25 mW transmitter reaches several kilometres.
Spreading factor
SF sets how many chips make up one symbol: SFn means 2ⁿ chips. Higher SF means each symbol takes longer, carries the same few bits, and survives worse conditions.
| SF | Chips/symbol | Bit rate (125 kHz) | Airtime, 20-byte payload | Relative range |
|---|---|---|---|---|
| 7 | 128 | ~5470 b/s | ~60 ms | Shortest |
| 8 | 256 | ~3125 b/s | ~110 ms | |
| 9 | 512 | ~1760 b/s | ~190 ms | |
| 10 | 1024 | ~980 b/s | ~370 ms | |
| 11 | 2048 | ~440 b/s | ~740 ms | |
| 12 | 4096 | ~250 b/s | ~1.5 s | Longest |
Three consequences worth internalising:
- Airtime is the scarce resource, not bandwidth. An SF12 packet occupies the channel for a second and a half. A handful of chatty SF12 nodes can saturate a cell.
- Different spreading factors are quasi-orthogonal, so a gateway receives SF7 and SF12 simultaneously on the same frequency. This is how one gateway serves thousands of nodes.
- Duty-cycle regulation bites. In the EU 868 MHz band most sub-bands are limited to 1% duty cycle, so an SF12 transmission buys you roughly two and a half minutes of enforced silence. In the US 902–928 MHz band the constraint is dwell time — 400 ms maximum — plus channel hopping, which is why US915 devices cannot use SF12 on 125 kHz channels at all.
Bandwidth, coding rate, and the sync word
Bandwidth is 125, 250 or 500 kHz. Wider is faster and less sensitive. Coding rate (4/5 through 4/8) sets the forward error correction overhead.
The sync word is a small detail with outsized diagnostic value:
| Sync word | Meaning |
|---|---|
0x34 |
Public LoRaWAN networks |
0x12 |
Private / point-to-point LoRa |
A receiver configured for one will not hear the other. When a student’s capture is empty and every other parameter looks right, this is usually why.
Regional bands
| Region | Band | Notes |
|---|---|---|
| EU868 | 863–870 MHz | Duty cycle limited (typically 1%) |
| US915 | 902–928 MHz | 64 × 125 kHz uplink + 8 × 500 kHz; dwell-time limited |
| AS923 | 920–925 MHz | Varies by country |
| AU915 | 915–928 MHz | Similar plan to US915 |
| IN865 | 865–867 MHz |
⚠️ Receiving is not transmitting. Passive reception is legal; unlicensed transmission in the ISM band is permitted only within Part 15 power and duty-cycle limits, and transmitting into someone else’s network is not a spectrum question at all. Course hardware, in lab, on course networks. See Radio Protocols.
Capturing it
LoRa’s narrow channels make it SDR-friendly — the opposite of WiFi.
| Tool | Notes |
|---|---|
| RTL-SDR / HackRF + URH | Visual identification; chirps are obvious |
gr-lora_sdr (GNU Radio) |
Full open-source LoRa demodulator |
| SX1301/SX1302 concentrator | A real gateway; receives 8 channels at once |
| RFM95 / Heltec / RAK node | Single-channel; what the course uses |
| CatSniffer, LoRa sniffers | Purpose-built multiprotocol boards |
For a 125 kHz channel you need at least 125 kS/s by Nyquist and realistically 250 kS/s or more for margin against filter roll-off — see the three capture parameters.
Worked example: identifying LoRa and reading its parameters
Sweep the band first to find the active channel:
$ rtl_power -f 902M:928M:25k -i 20 -e 2m -g 40 us915.csv
Number of frequency hops: 10
Dongle bandwidth: 2600000Hz
Total FFT bins: 1280
FFT bin size: 20312.50Hz
Reporting every 20 seconds
Read those numbers rather than skipping past them. rtl_power hops by the
dongle’s bandwidth, not by your bin size — 26 MHz in 2.6 MHz steps is ten
retunes, not one per megahertz — and it rounds the bin count to a power of two,
so the 25 kHz you asked for became 20.3 kHz. Both matter when you convert a
column index back to a frequency.
Then capture the hot channel and open it in URH:
$ rtl_sdr -f 903900000 -s 1024000 -g 40 -n 20480000 lora.iq
Found Rafael Micro R820T tuner
Sampling at 1024000 S/s.
Tuned to 903900000 Hz.
In the waterfall you are looking for the signature: a run of identical up-chirps (the preamble), then two down-chirps (the sync/frame delimiter), then chirps starting at varying offsets (the payload).
You can read the parameters straight off the display:
- Bandwidth is the vertical extent of the sweep — how much spectrum it covers.
- Symbol duration is the horizontal extent of one sweep. Since Tsym = 2^SF / BW, measuring one chirp gives you the spreading factor directly. A 125 kHz chirp lasting ~1 ms is SF7; ~32 ms is SF12.
- Preamble length is the count of leading identical chirps, normally 8.
That measurement is the exercise. Everything else is software.
LoRaWAN: the layer that adds security
Raw LoRa is bytes in, RF out. No confidentiality, no integrity, no replay protection — not as a defect, but because it is a physical layer and those are not physical-layer jobs. Capture the bytes, retransmit them, and the receiver cannot tell the difference. HW #4 demonstrates exactly this.
LoRaWAN adds a MAC layer and a network architecture:
End device <--LoRa--> Gateway <--IP--> Network Server <--> Application Server
(dumb relay) (holds NwkSKey) (holds AppSKey)
The gateway is deliberately dumb — it forwards packets it cannot read. All protocol logic lives in the network server.
Device classes:
| Class | Downlink behaviour | Power |
|---|---|---|
| A | Two short receive windows after each uplink | Lowest |
| B | Scheduled receive slots synchronised by beacons | Medium |
| C | Receiving continuously except when transmitting | Highest |
Class A is the default and means the network cannot reach a device until it speaks first — which is a security property as much as a power one. It also means a command queued for a sensor may sit for hours.
The key hierarchy
In LoRaWAN 1.0.x a root AppKey is provisioned per device, and joining derives two session keys:
| Key | Protects |
|---|---|
| NwkSKey | Frame integrity (the MIC) and MAC commands |
| AppSKey | Payload confidentiality, end to end to the application server |
The split lets a network operator route and verify frames without reading payloads — a sensible separation, and one reason LoRaWAN scales to shared public networks like The Things Network.
LoRaWAN 1.1 restructured this, splitting the root into NwkKey and AppKey and the session keys into four (FNwkSIntKey, SNwkSIntKey, NwkSEncKey, AppSKey) specifically so that a network server can no longer derive application keys. Adoption has been slow; networks frequently run 1.0 compatibility mode, which forfeits the benefit.
OTAA versus ABP
| OTAA | ABP | |
|---|---|---|
| Session keys | Derived fresh at each join | Fixed at manufacture |
| Join procedure | JoinRequest / JoinAccept | None — device is preloaded |
| Counters | Reset legitimately on rejoin | Must persist forever |
| Replay exposure | Lower | Higher |
ABP is the weaker choice and it is chosen constantly, because it avoids implementing the join. Static session keys plus a frame counter that resets on reboot gives an attacker a window in which previously captured frames are accepted again.
The join, and DevNonce
OTAA’s JoinRequest carries the JoinEUI, DevEUI and a DevNonce; the JoinAccept returns a JoinNonce, a DevAddr and network settings, encrypted under the AppKey.
The history of DevNonce is a good miniature of specification evolution:
- Pre-1.0.4: DevNonce was random. A device could repeat one by chance, and a network rejecting repeats would lock the device out — while an attacker replaying captured JoinRequests could exhaust the acceptable nonce space and deny service deliberately.
- 1.0.4 and 1.1: DevNonce is a monotonic counter, persisted in non-volatile memory, and the network server tracks the highest value seen and rejects anything not greater.
That fix is correct, and it moves the problem to exactly where every other protocol in this course has put it: the counter must survive power loss.
Replay protection is state
Uplinks and downlinks carry frame counters (FCntUp, FCntDown), transmitted as 16 bits with the upper 16 maintained at both ends. A receiver rejects a counter it has already seen. That is sound.
And a counter that must survive power loss has to live in flash, and flash has limited write endurance. So implementers write it every nth message, or skip forward in blocks on boot, or reset it and rely on the network to resynchronise. Every one of those choices reopens a replay window, and the network operator must then decide between rejecting a legitimately rebooted device forever and accepting a possibly replayed frame. They choose availability.
This is the generalisable lesson of the whole radio block, and it is not LoRaWAN-specific — Zigbee and Z-Wave have the identical tension. Replay protection is state, and embedded devices are bad at state.
What leaks without any key
As with Z-Wave, the header must be readable for the network to route:
+------+---------+-------+------+-------+--------------+-----+
| MHDR | DevAddr | FCtrl | FCnt | FPort | FRMPayload | MIC |
+------+---------+-------+------+-------+--------------+-----+
^^^^^^^ ^^^^ ^^^^^^^^^^^^
plaintext plaintext encrypted (AppSKey)
So a passive listener obtains the DevAddr — a stable per-session device identifier — and the frame counter, without holding a single key. That is enough to:
- Track a device’s presence and movement across gateways.
- Infer transmission schedules, and therefore behaviour.
- Detect counter resets, which mark reboots — and reboots are when replay windows open.
- Count devices on a network and estimate its size.
Payload confidentiality is not the same as privacy. Say so in the report.
The failure that actually happens
For all the protocol detail above, the most common real LoRaWAN compromise is not cryptographic. The AppKey is stored in the device’s flash, in plaintext, and the device is in a field where anyone can pick it up.
Recover the image via SWD or a flash dump (Dumping flash, JTAG and SWD), find the key, and you can clone the device, forge its telemetry, and decrypt everything it has ever sent. No AES was harmed.
This is why the hardware half of this course is not separate from the radio half — and it is the single highest-value check on a LoRaWAN assessment.
Key takeaways
- LoRa is chirp spread spectrum with no security at all; LoRaWAN is the MAC layer that adds it. Raw LoRa is trivially replayable by design.
- Processing gain lets LoRa decode below the noise floor, which is where the range comes from.
- Spreading factor trades airtime for range: SF12 costs ~1.5 s per packet, and airtime — not bandwidth — is the scarce resource.
- Different SFs are quasi-orthogonal, so one gateway serves many nodes on one frequency.
- Sync word
0x34is public LoRaWAN,0x12is private; a mismatch is the usual cause of an empty capture. - You can read bandwidth and spreading factor directly off a waterfall by measuring one chirp.
- ABP activation is weaker than OTAA: static keys plus a resettable counter reopens the replay window.
- DevNonce became a persisted monotonic counter in 1.0.4, which fixes join replay and relocates the problem to non-volatile storage.
- DevAddr and frame counters are plaintext, so tracking, scheduling inference and reboot detection need no keys at all.
- The realistic compromise is extracting the AppKey from unprotected flash, not attacking the protocol.
References
- Semtech, LoRa Modulation Basics (AN1200.22) — https://www.semtech.com/products/wireless-rf/lora-connect
- LoRa Alliance, specifications and resource hub — https://lora-alliance.org/resource-hub/
- LoRa Alliance, LoRaWAN 1.0.x Join Synch Issues and Remedies — https://lora-alliance.org/wp-content/uploads/2020/11/lorawan-1.0.x-join-synch-issues-remedies-v1.0.0.pdf
- The Things Network, What’s new in LoRaWAN 1.0.4 — https://www.thethingsnetwork.org/article/whats-new-in-lorawan-104-1
- The Things Network, end device activation (OTAA/ABP) — https://www.thethingsnetwork.org/docs/lorawan/end-device-activation/
- Butun, Pereira & Gidlund, Security Risk Analysis of LoRaWAN and Future Directions — https://www.mdpi.com/1999-5903/11/1/3
gr-lora_sdr, a GNU Radio LoRa transceiver — https://github.com/tapparelj/gr-lora_sdr- Universal Radio Hacker — https://github.com/jopohl/urh
- ChirpStack open-source LoRaWAN network server — https://www.chirpstack.io/
- FCC Part 15 rules (47 CFR Part 15) — https://www.ecfr.gov/current/title-47/chapter-I/subchapter-A/part-15
Related course pages: Radio Protocols · HW #4 · Lab 3 · Other IoT radios · Dumping flash · JTAG and SWD · Attacks
🛠️ Maintenance note: the airtime and bit-rate figures are computed for 125 kHz bandwidth and coding rate 4/5 — recompute them if the course radios are reconfigured, and treat them as approximate in any case. LoRaWAN 1.1 adoption has been “imminent” for years and is worth re-checking annually; 1.0.4 remains the practical target. Regional band plans are revised by the LoRa Alliance periodically, and the US915 dwell-time rules in particular should be verified against the current regional parameters document before being taught as fact.