10 LoRaWAN Security and Joining
10.1 Learning Objectives
By the end of this chapter, you will be able to:
- Explain Security Architecture: Describe the dual-layer encryption model with NwkSKey and AppSKey
- Compare Activation Methods: Differentiate OTAA and ABP joining procedures
- Evaluate Security Trade-offs: Assess when to use OTAA vs ABP based on deployment requirements
- Implement Best Practices: Apply security guidelines for production LoRaWAN deployments
10.2 Prerequisites
Before diving into this chapter, you should be familiar with:
- LoRaWAN Network Topology: Understanding network components and server roles
- LoRaWAN Device Classes: Device communication patterns
Key Concepts
- OTAA (Over-the-Air Activation): Secure device joining method using a join request/accept handshake to derive session keys; preferred for production deployments.
- ABP (Activation By Personalization): Device activation method with hardcoded session keys; simpler but less secure due to fixed DevAddr and no join procedure.
- AppKey: 128-bit root key used in OTAA join procedure to derive session keys (NwkSKey, AppSKey); must be kept secret and unique per device.
- NwkSKey (Network Session Key): 128-bit AES key derived during OTAA; used to authenticate MAC layer messages between device and network server.
- AppSKey (Application Session Key): 128-bit AES key derived during OTAA; used to encrypt/decrypt application payload between device and application server.
- DevEUI: 64-bit globally unique device identifier assigned by the device manufacturer; used during OTAA join to identify the joining device.
- Frame Counter (FCnt): Uplink/downlink counter preventing replay attacks; must be persistent across resets for ABP devices and reset on OTAA rejoin.
LoRaWAN uses two layers of encryption to protect your data:
- Network Layer (NwkSKey): Protects the network infrastructure—ensures only authorized devices can use the network
- Application Layer (AppSKey): Protects your actual sensor data—even the network operator can’t read it!
Analogy: Think of sending a letter through a courier service: - NwkSKey: The sealed envelope that proves you’re a valid customer (network can verify) - AppSKey: The coded message inside that only you and the recipient understand (courier can’t read)
Two ways to get these keys:
- OTAA (Over-The-Air Activation): Like registering for a new SIM card—you authenticate and get fresh keys each time
- ABP (Activation By Personalization): Like a pre-paid SIM—keys are pre-loaded at the factory, simpler but less secure
| Term | Simple Explanation |
|---|---|
| NwkSKey | Network Session Key—proves you’re allowed on the network |
| AppSKey | Application Session Key—encrypts your sensor data |
| OTAA | Join procedure that generates fresh keys (more secure) |
| ABP | Pre-programmed keys, no join needed (simpler but riskier) |
| DevEUI | Device’s unique identifier (like a MAC address) |
| AppKey | Root secret used to derive session keys in OTAA |
“LoRaWAN uses two separate keys to protect your data!” Sammy the Sensor said. “The NwkSKey is like my ID badge – it proves I am allowed on the network. The AppSKey is like my personal diary lock – it encrypts my sensor data so that even the network operator cannot read it. Double protection!”
“OTAA is the secure way to join,” Lila the LED explained. “When I power on, I send a Join Request with my unique DevEUI and a challenge. The network server checks my credentials and sends back fresh session keys. It is like getting a new password every time you log in – even if someone steals today’s keys, they will not work tomorrow!”
Max the Microcontroller warned, “ABP is simpler but dangerous for production. The keys are programmed at the factory and never change. If the device loses power and the frame counter resets, the network thinks it is a replay attack and rejects all messages. I have seen entire deployments go silent because of this. Always use OTAA in production!”
“The dual-key system is really clever,” Bella the Battery added. “The network only needs the NwkSKey to validate and route messages – it never sees the AppSKey. So even if the network server is compromised, your actual sensor data stays encrypted. This end-to-end security is one of the reasons LoRaWAN is trusted for smart metering and critical infrastructure.”
10.3 Security Architecture
LoRaWAN provides end-to-end security with two encryption layers:
10.3.1 Network Session Key (NwkSKey)
- Validates message integrity (MIC calculation)
- Encrypts MAC commands
- Known only to device and network server
10.3.2 Application Session Key (AppSKey)
- Encrypts application payload
- Provides end-to-end encryption
- Network server cannot decrypt application data
10.3.3 Security Properties
| Property | Protection | Key Used |
|---|---|---|
| Confidentiality | Payload encrypted end-to-end | AppSKey |
| Integrity | MIC prevents tampering | NwkSKey |
| Authentication | Only valid devices accepted | NwkSKey |
| Replay Protection | Frame counter prevents replays | NwkSKey |
Let’s quantify the security strength of LoRaWAN’s AES-128 encryption. The key space size determines how long a brute-force attack would take:
\(\text{Key Space} = 2^{128} = 3.4 \times 10^{38}\) possible keys
For a brute-force attack testing keys at rate \(R\) keys/second, the expected time to find the correct key is:
\(T = \frac{2^{128}}{2R} = \frac{2^{127}}{R}\)
With a modern GPU achieving \(10^9\) AES operations/second:
\(T = \frac{2^{127}}{10^9} = \frac{1.7 \times 10^{38}}{10^9} = 1.7 \times 10^{29} \text{ seconds}\)
Converting to years: \(\frac{1.7 \times 10^{29}}{365.25 \times 24 \times 3600} = 5.4 \times 10^{21}\) years
This is 5.4 billion trillion years — far longer than the age of the universe (13.8 billion years). Even with a million GPUs working in parallel, brute-forcing AES-128 remains computationally infeasible.
Message Integrity Code (MIC) strength: LoRaWAN uses a 32-bit MIC (truncated AES-CMAC). Collision probability for forged messages:
\(P_{\text{forge}} = \frac{1}{2^{32}} = 2.3 \times 10^{-10}\)
With 1 million messages, expected forgeries: \(10^6 \times 2.3 \times 10^{-10} = 0.00023\) (negligible). The MIC provides adequate integrity protection for IoT sensor data while keeping overhead low (4 bytes per message).
10.4 Joining a LoRaWAN Network
Devices can join a network using two methods:
10.4.1 Over-The-Air Activation (OTAA)
Recommended method - More secure, keys derived dynamically
- Device sends Join Request with DevEUI and AppEUI
- Network server validates and sends Join Accept
- Session keys derived from AppKey and nonces
- Device assigned DevAddr for the session
OTAA Credentials:
| Credential | Size | Purpose |
|---|---|---|
| DevEUI | 64-bit | Globally unique device identifier |
| AppEUI/JoinEUI | 64-bit | Application identifier |
| AppKey | 128-bit | Root key for deriving session keys |
10.4.2 Activation By Personalization (ABP)
Simpler but less secure - Pre-provisioned keys
- DevAddr, NwkSKey, and AppSKey programmed at manufacturing
- No join procedure required
- Useful for constrained devices or private networks
- Less secure: keys never change
ABP Pre-Provisioned Values:
| Value | Size | Notes |
|---|---|---|
| DevAddr | 32-bit | Network address (pre-assigned) |
| NwkSKey | 128-bit | Pre-programmed, never changes |
| AppSKey | 128-bit | Pre-programmed, never changes |
10.4.3 OTAA vs ABP Comparison
| Aspect | OTAA | ABP |
|---|---|---|
| Security | High (keys rotate on rejoin) | Lower (static keys) |
| Setup Complexity | Requires join procedure | Simpler (no join) |
| Key Compromise | Rejoin generates new keys | Keys compromised forever |
| Frame Counter | Resets on rejoin | Must persist across reboots |
| Roaming | Supported | Not supported |
| Recommended | Yes (production) | Testing only |
10.5 Knowledge Check
Test your understanding of LoRaWAN security.
10.6 Common Pitfalls
The Mistake: Deploying ABP (Activation By Personalization) devices without implementing non-volatile frame counter storage, causing frame counter reset after power loss and subsequent message rejection.
Why It Happens: ABP simplifies deployment by avoiding join procedures, but developers overlook that LoRaWAN network servers reject messages with frame counters lower than previously seen (replay attack protection). When an ABP device reboots and resets its frame counter to zero, all subsequent messages are silently dropped.
The Fix: For ABP devices, store the frame counter in EEPROM or flash memory, incrementing by 100+ on each save to account for messages sent before the next save. Better yet, use OTAA activation which generates fresh session keys and resets frame counters on each join, eliminating this problem entirely.
The Mistake: Developers choose Activation By Personalization (ABP) over OTAA because it appears simpler (no join procedure, works immediately), then discover critical issues in production: frame counter resets causing packet rejection, security vulnerabilities from static keys, and inability to roam between network servers.
Why It Happens: ABP looks attractive during prototyping:
- Instant gratification: Device transmits immediately without waiting for join
- Deterministic behavior: Same session keys every boot, easier to debug
- Simpler network setup: No Join Server required
- Works in poor coverage: No two-way communication needed for activation
But ABP creates severe production problems:
- Frame counter vulnerability: After power loss, counter resets to 0. Network server expects higher counter and rejects all messages as replays
- Static keys = static risk: If AppSKey/NwkSKey are compromised, device must be physically retrieved and re-provisioned
- No server-side key refresh: Keys never change over device lifetime (potentially 10+ years)
- Roaming impossible: Device is permanently bound to one network server
The Fix: Use OTAA for production, ABP only for specific constrained scenarios:
When ABP is acceptable:
- Single-transmission sensors (measure, transmit, die)
- Development/testing only
- Private networks with physical security
- Devices with guaranteed power (no resets)
When OTAA is required (most production cases): - Any device that may power-cycle - Multi-year deployments - Public network connectivity (TTN, Helium) - Devices that may roam between regions/operators
If you must use ABP, implement frame counter persistence:
// Store frame counter in EEPROM/Flash every N messages
void save_frame_counter(uint32_t fcnt) {
// Write to non-volatile storage
eeprom_write_dword(FCNT_ADDR, fcnt);
}
uint32_t load_frame_counter() {
uint32_t fcnt = eeprom_read_dword(FCNT_ADDR);
// Add safety margin to handle unexpected resets
return fcnt + 100; // Skip 100 counts to ensure acceptance
}Production deployment statistics: In a 5-year agricultural deployment with 600 ABP devices, 18% required manual intervention due to frame counter issues (power outages, firmware updates). The same deployment with OTAA would have zero such interventions, as each rejoin generates fresh keys and resets counters server-side.
The Mistake: Developers swap or confuse the AppEUI (JoinEUI in LoRaWAN 1.1), AppKey, and DevEUI when registering devices on the network server, or use the same value for multiple fields. The join procedure fails silently with no clear error message indicating which credential is incorrect.
Why It Happens: OTAA requires three distinct 128-bit (AppKey) and 64-bit (DevEUI, JoinEUI) values that look similar in hex format. Confusion arises from:
- Naming changes: LoRaWAN 1.0 uses
AppEUI, LoRaWAN 1.1 renamed it toJoinEUI- different network servers use different terminology - Copy-paste errors: All values are 16 or 32 hex characters; easy to paste into wrong field
- Sample code defaults: Tutorials often use identical placeholder values (
0x00...00) for all fields - Key vs EUI confusion: AppKey is 128-bit (16 bytes), DevEUI/JoinEUI are 64-bit (8 bytes) - wrong length indicates wrong field
The Fix: Understand and carefully verify each OTAA credential:
- DevEUI (64-bit): Unique device identifier, typically from hardware. Format:
70B3D57ED00XXXXX - JoinEUI/AppEUI (64-bit): Application identifier, can be shared across device fleet. Often all-zeros for TTN:
0000000000000000 - AppKey (128-bit): Root key for session key derivation. MUST be unique per device, randomly generated:
2B7E151628AED2A6ABF7158809CF4F3C
OTAA credential checklist:
Before deploying, verify:
[ ] DevEUI is 8 bytes (16 hex chars)
[ ] JoinEUI/AppEUI is 8 bytes (16 hex chars)
[ ] AppKey is 16 bytes (32 hex chars)
[ ] DevEUI is unique per device (not copied from tutorial)
[ ] AppKey is randomly generated (not default all-zeros or all-Fs)
[ ] Network server shows same values as device firmware
[ ] Byte order matches (MSB vs LSB) between device and server
Common byte-order trap: Some platforms display DevEUI as MSB-first (70B3D57ED00XXXXX), others as LSB-first (XXXXX00D7ED5B370). If Join Request appears in gateway logs but network server rejects it, suspect byte-order mismatch. The Things Stack uses MSB format; verify your device library’s convention.
The Mistake: Developers deploy thousands of devices with OTAA activation, then power them all on simultaneously (e.g., after a firmware update or mass deployment). All devices send Join Requests at once, overwhelming the network server and causing most joins to fail.
Why It Happens: OTAA requires a successful handshake: device sends Join Request, network responds with Join Accept during the RX1/RX2 windows (1-2 seconds after request). With EU868’s 1% duty cycle, a gateway can only transmit ~36 seconds per hour on downlink. If 500 devices join simultaneously, the gateway can only respond to ~30 devices per hour (each Join Accept takes ~1.2 seconds at SF12). The other 470 devices timeout and retry, creating a “join storm.”
The Fix: Implement randomized join backoff. Before sending a Join Request, each device should:
- Wait a random delay:
delay_ms = random(0, 30000)(spread joins over 30 seconds) - For large deployments (1000+ devices), use longer windows:
delay_ms = random(0, device_count * 60)(1 minute per 1000 devices) - Configure exponential backoff on failure:
retry_delay = min(2^attempt * 5000, 3600000)(5s, 10s, 20s… up to 1 hour) - Pre-calculate DevNonce to avoid replay issues: store last used DevNonce in non-volatile memory
Example for 2000-device deployment:
// Spread joins over 2 hours (3600ms * 2)
initial_delay = random(0, 7200000);
sleep(initial_delay);
send_join_request();
This reduces peak join load from 2000 simultaneous requests to ~0.3 requests/second, ensuring 99%+ successful joins on first attempt.
10.7 Worked Example: Securing a 2,000-Sensor Agricultural Deployment
Scenario: ValleyFarms deploys 2,000 LoRaWAN soil moisture sensors across 5,000 acres of vineyards. Each sensor transmits 12-byte readings every 15 minutes. The network uses 8 Kerlink Wirnet iStation gateways connected to a ChirpStack v4 network server. The team must choose between OTAA and ABP activation and design the security architecture.
10.7.1 Requirements Analysis
| Requirement | Detail |
|---|---|
| Devices | 2,000 soil moisture sensors (Class A) |
| Battery life target | 5 years on 2x AA lithium (3.6V, 2600 mAh each) |
| Network | Private ChirpStack v4, 8 gateways |
| Uplink frequency | Every 15 minutes (96 messages/day/device) |
| Downlink need | Firmware updates 1-2x per year, occasional config changes |
| Physical access | Sensors buried at root depth, retrieval costs ~$35/device |
| Threat model | Competitor data theft, data tampering for insurance fraud |
10.7.2 Option A: ABP Activation
Provisioning workflow: Program DevAddr + NwkSKey + AppSKey at factory, ship to field.
| Cost Item | Per Device | Total (2,000) |
|---|---|---|
| Factory provisioning (key injection) | $2.50 | $5,000 |
| Key management database | – | $1,200/year |
| Frame counter EEPROM (MX25V1006E) | $0.45 | $900 |
| Flash write overhead (100 writes/day) | 0.8 uA avg | +2.1% battery drain |
Risk analysis (5-year horizon):
- Power outage recovery: 18% of field devices experience brown-outs per year (irrigation pump surges). With frame counter persistence, recovery rate is 94%. Without it, devices go permanently silent until physically retrieved.
- Key compromise: Static keys mean one leaked AppKey compromises all historical data for that device. Physical retrieval to re-key costs $35/device.
- Estimated annual maintenance cost: $35 x 2,000 x 0.06 (6% failure rate) = $4,200/year in field visits.
10.7.3 Option B: OTAA Activation
Provisioning workflow: Program DevEUI + AppKey at factory. Device auto-joins on power-up.
| Cost Item | Per Device | Total (2,000) |
|---|---|---|
| Factory provisioning (root key only) | $1.80 | $3,600 |
| Join Server license (ChirpStack) | – | $0 (open source) |
| Join energy overhead | 0.12 mAh per join | Negligible (2-3 joins/year) |
| Additional join traffic | 2 extra packets/join | < 0.01% duty cycle impact |
Risk analysis (5-year horizon):
- Power outage recovery: Device simply re-joins with fresh session keys. No frame counter persistence needed. 99.7% auto-recovery rate.
- Key compromise: Session keys rotate on every rejoin. Even if NwkSKey/AppSKey are extracted, rejoin invalidates them. Root AppKey compromise requires physical access to device (buried in soil).
- Estimated annual maintenance cost: $35 x 2,000 x 0.003 (0.3% failure rate) = $210/year in field visits.
10.7.4 5-Year Total Cost of Ownership
| Category | ABP | OTAA |
|---|---|---|
| Factory provisioning | $5,000 | $3,600 |
| Key management infrastructure | $6,000 | $0 |
| EEPROM components | $900 | $0 |
| Annual field maintenance (x5) | $21,000 | $1,050 |
| Security incident response (est.) | $8,000 | $500 |
| 5-year total | $40,900 | $5,150 |
10.7.5 Decision
ValleyFarms chose OTAA with the following implementation details:
- Randomized join backoff:
delay_ms = device_id * 3600to spread 2,000 joins over 2 hours at power-up - ADR enabled: Network server optimizes SF per device (SF7-SF10 depending on distance)
- Rejoin interval: Programmed to rejoin every 30 days to rotate session keys
- AppKey diversity: Each device has a unique 128-bit AppKey (not a shared fleet key)
Result after 18 months: 99.4% uptime, zero security incidents, 3 devices replaced (physical damage), zero field visits for connectivity issues.
10.8 Practice Exercise
10.9 Summary
LoRaWAN security provides:
- Dual-layer encryption: NwkSKey for network, AppSKey for application (end-to-end)
- Flexible activation: OTAA (secure, dynamic keys) vs ABP (simple, static keys)
- Integrity protection: MIC prevents message tampering
- Replay protection: Frame counters prevent message replay attacks
Key Recommendation: Always use OTAA for production deployments. ABP should only be used for testing or specific constrained scenarios with proper frame counter persistence.
10.10 What’s Next?
| Direction | Chapter | Description |
|---|---|---|
| Next | LoRaWAN Link Budget and ADR | Range calculations, spreading factor optimization, and the Adaptive Data Rate algorithm |
| Previous | LoRaWAN Device Classes | Class A, B, and C communication patterns and power trade-offs |
| Parent | LoRaWAN Architecture | Overview of all LoRaWAN architecture chapters |
| Related | Encryption Architecture | AES-128 encryption and end-to-end security fundamentals |
| Related | IoT Device Security | Broader IoT security threats and mitigation strategies |