1079  LoRaWAN Security and Joining

1079.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

1079.2 Prerequisites

Before diving into this chapter, you should be familiar with:

LoRaWAN uses two layers of encryption to protect your data:

  1. Network Layer (NwkSKey): Protects the network infrastructure—ensures only authorized devices can use the network
  2. 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

1079.3 Security Architecture

LoRaWAN provides end-to-end security with two encryption layers:

1079.3.1 Network Session Key (NwkSKey)

  • Encrypts MAC layer payload
  • Validates message integrity (MIC)
  • Known only to device and network server

1079.3.2 Application Session Key (AppSKey)

  • Encrypts application payload
  • Provides end-to-end encryption
  • Network server cannot decrypt application data

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D', 'background': '#ffffff', 'mainBkg': '#2C3E50', 'secondBkg': '#16A085', 'tertiaryBkg': '#E67E22'}}}%%
graph TB
    subgraph device[" End Device "]
        PAYLOAD[Application Payload<br/>Sensor Data]
        APPENC[Encrypt with AppSKey<br/>AES-128]
        MACENC[Add MAC Header<br/>Encrypt with NwkSKey]
        MIC[Calculate MIC<br/>NwkSKey]
    end

    subgraph network[" Network Server "]
        NMIC[Verify MIC<br/>NwkSKey]
        NMAC[Decrypt MAC Layer<br/>NwkSKey]
        NFORWARD[Forward Encrypted<br/>App Payload]
    end

    subgraph app[" Application Server "]
        ADEC[Decrypt Payload<br/>AppSKey]
        ADATA[Application Data<br/>Plaintext]
    end

    PAYLOAD --> APPENC
    APPENC --> MACENC
    MACENC --> MIC

    MIC -->|LoRa RF| NMIC
    NMIC --> NMAC
    NMAC -->|Can't decrypt<br/>app payload| NFORWARD

    NFORWARD --> ADEC
    ADEC --> ADATA

    style device fill:#f0f0f0,stroke:#2C3E50,stroke-width:2px
    style network fill:#f0f0f0,stroke:#16A085,stroke-width:2px
    style app fill:#f0f0f0,stroke:#E67E22,stroke-width:2px
    style PAYLOAD fill:#2C3E50,stroke:#16A085,color:#fff
    style APPENC fill:#E67E22,stroke:#2C3E50,color:#fff
    style MACENC fill:#16A085,stroke:#2C3E50,color:#fff
    style MIC fill:#16A085,stroke:#2C3E50,color:#fff
    style NMIC fill:#16A085,stroke:#2C3E50,color:#fff
    style NMAC fill:#16A085,stroke:#2C3E50,color:#fff
    style NFORWARD fill:#7F8C8D,stroke:#2C3E50,color:#fff
    style ADEC fill:#E67E22,stroke:#2C3E50,color:#fff
    style ADATA fill:#E67E22,stroke:#2C3E50,color:#fff

Figure 1079.1: LoRaWAN Two-Layer Security: AppSKey and NwkSKey Encryption Flow {fig-alt=“LoRaWAN two-layer security architecture showing application payload encrypted with AppSKey (end-to-end security between device and application server), then MAC layer encrypted with NwkSKey (device to network server). Network Server can verify MIC and decrypt MAC layer but cannot access application payload, ensuring end-to-end encryption. Both use AES-128.”}

1079.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

1079.4 Joining a LoRaWAN Network

Devices can join a network using two methods:

1079.4.1 Over-The-Air Activation (OTAA)

Recommended method - More secure, keys derived dynamically

  1. Device sends Join Request with DevEUI and AppEUI
  2. Network server validates and sends Join Accept
  3. Session keys derived from AppKey and nonces
  4. Device assigned DevAddr for the session

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085'}}}%%
sequenceDiagram
    participant D as End Device
    participant G as Gateway
    participant NS as Network Server
    participant JS as Join Server

    Note over D: Has DevEUI, AppEUI, AppKey
    D->>G: Join Request (DevEUI, AppEUI, DevNonce)
    G->>NS: Forward Join Request
    NS->>JS: Verify credentials
    JS->>NS: Approved + AppKey
    Note over NS: Derive NwkSKey, AppSKey
    NS->>G: Join Accept (DevAddr, AppNonce)
    G->>D: Join Accept (encrypted with AppKey)
    Note over D: Derive NwkSKey, AppSKey
    D->>G: First uplink with new session keys

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

1079.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

1079.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

1079.5 Knowledge Check

Test your understanding of LoRaWAN security.

Question 1: A LoRaWAN device uses OTAA (Over-The-Air Activation) to join a network. What security advantage does OTAA provide over ABP (Activation By Personalization)?

Explanation: OTAA’s security advantage is key derivation: each join procedure generates fresh NwkSKey and AppSKey from the root AppKey and random nonces. If session keys are compromised, the device can rejoin to get new keys—the attacker loses access. With ABP, keys are pre-programmed and never change; a compromised key remains compromised forever. Both use the same encryption (AES-128). OTAA requires the root AppKey as a pre-shared secret. The Join Request isn’t encrypted but is authenticated via MIC. OTAA also provides replay protection through DevNonce uniqueness requirements.

Question 2: In LoRaWAN’s security model, the network server can verify message integrity but cannot read application data. Which keys make this possible?

Explanation: LoRaWAN’s dual-layer encryption separates concerns. The NwkSKey is shared between device and network server—used for MAC-layer operations (MIC verification, MAC command encryption). The AppSKey is shared between device and application server only—the network server never sees it. This allows the network server to authenticate devices and manage the network without being able to read sensor data. It’s a key architectural feature ensuring end-to-end privacy.

1079.6 Common Pitfalls

CautionPitfall: Using ABP Activation Without Frame Counter Persistence

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.

CautionPitfall: Choosing ABP “Because It’s Simpler” for Production Deployments

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.

CautionPitfall: Confusing AppEUI/JoinEUI with AppKey in OTAA Provisioning

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 to JoinEUI - 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:

  1. DevEUI (64-bit): Unique device identifier, typically from hardware. Format: 70B3D57ED00XXXXX
  2. JoinEUI/AppEUI (64-bit): Application identifier, can be shared across device fleet. Often all-zeros for TTN: 0000000000000000
  3. 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.

CautionPitfall: Ignoring Join Request Timing in OTAA Deployments

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:

  1. Wait a random delay: delay_ms = random(0, 30000) (spread joins over 30 seconds)
  2. For large deployments (1000+ devices), use longer windows: delay_ms = random(0, device_count * 60) (1 minute per 1000 devices)
  3. Configure exponential backoff on failure: retry_delay = min(2^attempt * 5000, 3600000) (5s, 10s, 20s… up to 1 hour)
  4. 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.

1079.7 Practice Exercise

NoteExercise: OTAA vs ABP Security Comparison

Objective: Compare Over-The-Air Activation and Activation By Personalization security models

Tasks: 1. Implement join procedure simulation: - OTAA: Device sends Join Request with DevEUI, AppEUI, DevNonce (random 2-byte counter). Network server authenticates using AppKey (pre-shared 128-bit key), derives NwkSKey and AppSKey from AppKey + JoinNonce + DevNonce, sends Join Accept encrypted with AppKey - ABP: Device pre-programmed with fixed DevAddr, NwkSKey, AppSKey. No join procedure, device starts transmitting immediately 2. Security analysis: - What happens if NwkSKey is compromised for OTAA device? (Attacker can decrypt MAC commands, inject fake messages until device rejoins and gets new session keys) - What happens if NwkSKey is compromised for ABP device? (Permanent compromise - keys never change unless manually reprogrammed) - Replay attack resistance: OTAA uses frame counter (FCnt) starting at 0 after each join. ABP must persist FCnt across reboots or be vulnerable. What if ABP device loses power? 3. Deployment scenarios: - Firmware update via FUOTA (Firmware Update Over The Air): Which activation method is safer? (OTAA - can rejoin with new keys after update) - Factory-sealed sensor with 10-year battery life: Which is more practical? (ABP - no join procedure saves battery, no rejoin after network server reset)

Expected Outcome: - OTAA more secure (keys rotate on rejoin, AppKey never transmitted over air) - ABP simpler (no join latency, no join failures) but permanent key compromise risk - OTAA recommended for most deployments unless extreme power constraints or network server guaranteed never to reset - Understanding that Join Accept is encrypted (prevents attacker from learning session keys even if AppKey later compromised)

1079.8 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.

TipWhat’s Next?

Continue to LoRaWAN Link Budget and ADR to learn about range calculations, spreading factor optimization, and the Adaptive Data Rate algorithm.