Back to Ruview

AI Security Modules -- WiFi-DensePose Edge Intelligence

docs/edge-modules/ai-security.md

0.7.011.6 KB
Original Source

AI Security Modules -- WiFi-DensePose Edge Intelligence

Tamper detection and behavioral anomaly profiling that protect the sensing system from manipulation. These modules detect replay attacks, signal injection, jamming, and unusual behavior patterns -- all running on-device with no cloud dependency.

Overview

ModuleFileWhat It DoesEvent IDsBudget
Signal Shieldais_prompt_shield.rsDetects replay, injection, and jamming attacks on CSI data820-823S (<5 ms)
Behavioral Profilerais_behavioral_profiler.rsLearns normal behavior and detects anomalous deviations825-828S (<5 ms)

Signal Shield (ais_prompt_shield.rs)

What it does: Detects three types of attack on the WiFi sensing system:

  1. Replay attacks: An adversary records legitimate CSI frames and plays them back to fool the sensor into seeing a "normal" scene while actually present in the room.
  2. Signal injection: An adversary transmits a strong WiFi signal to overpower the legitimate CSI, creating amplitude spikes across many subcarriers.
  3. Jamming: An adversary floods the WiFi channel with noise, degrading the signal-to-noise ratio below usable levels.

How it works:

  • Replay detection: Each frame's features (mean phase, mean amplitude, amplitude variance) are quantized and hashed using FNV-1a. The hash is stored in a 64-entry ring buffer. If a new frame's hash matches any recent hash, it flags a replay.
  • Injection detection: If more than 25% of subcarriers show a >10x amplitude jump from the previous frame, it flags injection.
  • Jamming detection: The module calibrates a baseline SNR (signal / sqrt(variance)) over the first 100 frames. If the current SNR drops below 10% of baseline for 5+ consecutive frames, it flags jamming.

Public API

rust
use wifi_densepose_wasm_edge::ais_prompt_shield::PromptShield;

let mut shield = PromptShield::new();                     // const fn, zero-alloc
let events = shield.process_frame(&phases, &amplitudes);  // per-frame analysis
let calibrated = shield.is_calibrated();                  // true after 100 frames
let frames = shield.frame_count();                        // total frames processed

Events

Event IDConstantValueFrequency
820EVENT_REPLAY_ATTACK1.0 (detected)On detection (cooldown: 40 frames)
821EVENT_INJECTION_DETECTEDFraction of subcarriers with spikes [0.25, 1.0]On detection (cooldown: 40 frames)
822EVENT_JAMMING_DETECTEDSNR drop in dB (10 * log10(baseline/current))On detection (cooldown: 40 frames)
823EVENT_SIGNAL_INTEGRITYComposite integrity score [0.0, 1.0]Every 20 frames

Configuration Constants

ConstantValuePurpose
MAX_SC32Maximum subcarriers processed
HASH_RING64Size of replay detection hash ring buffer
INJECTION_FACTOR10.0Amplitude jump threshold (10x previous)
INJECTION_FRAC0.25Minimum fraction of subcarriers with spikes
JAMMING_SNR_FRAC0.10SNR must drop below 10% of baseline
JAMMING_CONSEC5Consecutive low-SNR frames required
BASELINE_FRAMES100Calibration period length
COOLDOWN40Frames between repeated alerts (2 seconds at 20 Hz)

Signal Integrity Score

The composite score (event 823) is emitted every 20 frames and ranges from 0.0 (compromised) to 1.0 (clean):

FactorScore ReductionCondition
Replay detected-0.4Frame hash matches ring buffer
Injection detectedup to -0.3Proportional to injection fraction
SNR degradationup to -0.3Proportional to SNR drop below baseline

FNV-1a Hash Details

The hash function quantizes three frame statistics to integer precision before hashing:

hash = FNV_OFFSET (2166136261)
for each of [mean_phase*100, mean_amp*100, amp_variance*100]:
    for each byte in value.to_le_bytes():
        hash ^= byte
        hash = hash.wrapping_mul(FNV_PRIME)   // FNV_PRIME = 16777619

This means two frames must have nearly identical statistical profiles (within 1% quantization) to trigger a replay alert.

Example: Detecting a Replay Attack

Calibration (frames 1-100):
  Normal CSI with varying phases -> baseline SNR established
  No alerts emitted during calibration

Frame 150: Normal operation
  phases = [0.31, 0.28, ...], amps = [1.02, 0.98, ...]
  hash = 0xA7F3B21C -> stored in ring buffer
  No alerts

Frame 200: Attacker replays frame 150 exactly
  phases = [0.31, 0.28, ...], amps = [1.02, 0.98, ...]
  hash = 0xA7F3B21C -> MATCH found in ring buffer!
  -> EVENT_REPLAY_ATTACK = 1.0
  -> EVENT_SIGNAL_INTEGRITY = 0.6 (reduced by 0.4)

Example: Detecting Signal Injection

Frame 300: Normal amplitudes
  amps = [1.0, 1.1, 0.9, 1.0, ...]

Frame 301: Adversary injects strong signal
  amps = [15.0, 12.0, 14.0, 13.0, ...]  (>10x jump on all subcarriers)
  injection_fraction = 1.0 (100% of subcarriers spiked)
  -> EVENT_INJECTION_DETECTED = 1.0
  -> EVENT_SIGNAL_INTEGRITY = 0.4

Behavioral Profiler (ais_behavioral_profiler.rs)

What it does: Learns what "normal" behavior looks like over time, then detects anomalous deviations. It builds a 6-dimensional behavioral profile using online statistics (Welford's algorithm) and flags when new observations deviate significantly from the learned baseline.

How it works: Every 200 frames, the module computes a 6D feature vector from the observation window. During the learning phase (first 1000 frames), it trains Welford accumulators for each dimension. After maturity, it computes per-dimension Z-scores and a combined RMS Z-score. If the combined score exceeds 3.0, an anomaly is reported.

The 6 Behavioral Dimensions

#DimensionDescriptionTypical Range
0Presence RateFraction of frames with presence[0, 1]
1Average MotionMean motion energy in window[0, ~5]
2Average PersonsMean person count[0, ~4]
3Activity VarianceVariance of motion energy[0, ~10]
4Transition RatePresence state changes per frame[0, 0.5]
5Dwell TimeAverage consecutive presence run length[0, 200]

Public API

rust
use wifi_densepose_wasm_edge::ais_behavioral_profiler::BehavioralProfiler;

let mut bp = BehavioralProfiler::new();                   // const fn
let events = bp.process_frame(present, motion, n_persons); // per-frame
let mature = bp.is_mature();                               // true after learning
let anomalies = bp.total_anomalies();                      // cumulative count
let mean = bp.dim_mean(0);                                 // mean of dimension 0
let var = bp.dim_variance(1);                              // variance of dim 1

Events

Event IDConstantValueFrequency
825EVENT_BEHAVIOR_ANOMALYCombined Z-score (RMS, > 3.0)On detection (cooldown: 100 frames)
826EVENT_PROFILE_DEVIATIONIndex of most deviant dimension (0-5)Paired with anomaly
827EVENT_NOVEL_PATTERNCount of dimensions with Z > 2.0When 3+ dimensions deviate
828EVENT_PROFILE_MATURITYDays since sensor startOn maturity + periodically

Configuration Constants

ConstantValuePurpose
N_DIM6Behavioral dimensions
LEARNING_FRAMES1000Frames before profiler matures
ANOMALY_Z3.0Combined Z-score threshold for anomaly
NOVEL_Z2.0Per-dimension Z-score threshold for novelty
NOVEL_MIN3Minimum deviating dimensions for NOVEL_PATTERN
OBS_WIN200Observation window size (frames)
COOLDOWN100Frames between repeated anomaly alerts
MATURITY_INTERVAL72000Frames between maturity reports (1 hour at 20 Hz)

Welford's Online Algorithm

Each dimension maintains running statistics without storing all past values:

On each new observation x:
    count += 1
    delta = x - mean
    mean += delta / count
    m2 += delta * (x - mean)

Variance = m2 / count
Z-score  = |x - mean| / sqrt(variance)

This is numerically stable and requires only 12 bytes per dimension (count + mean + m2).

Example: Detecting an Intruder's Behavioral Signature

Learning phase (day 1-2):
  Normal pattern: 1 person, present 8am-10pm, moderate motion
  Profile matures -> EVENT_PROFILE_MATURITY = 0.58 (days)

Day 3, 3am:
  Observation window: presence=1, high motion, 1 person
  Z-scores: presence_rate=2.8, motion=4.1, persons=0.3,
            variance=3.5, transition=2.2, dwell=1.9
  Combined Z = sqrt(mean(z^2)) = 3.4 > 3.0
  -> EVENT_BEHAVIOR_ANOMALY = 3.4
  -> EVENT_PROFILE_DEVIATION = 1 (motion dimension most deviant)
  -> EVENT_NOVEL_PATTERN = 3 (3 dimensions above Z=2.0)

Threat Model

Attacks These Modules Detect

AttackDetection ModuleMethodFalse Positive Rate
CSI frame replaySignal ShieldFNV-1a hash ring matchingLow (1% quantization)
Signal injection (e.g., rogue AP)Signal Shield>25% subcarriers with >10x amplitude spikeVery low
Broadband jammingSignal ShieldSNR drop below 10% of baseline for 5+ framesVery low
Narrowband jammingPartially -- Signal ShieldMay not trigger if < 25% subcarriers affectedMedium
Behavioral anomaly (intruder at unusual time)Behavioral ProfilerCombined Z-score > 3.0 across 6 dimensionsLow after maturation
Gradual environmental changeBehavioral ProfilerWelford stats adapt, may flag if change is abruptVery low

Attacks These Modules Cannot Detect

AttackWhy NotRecommended Mitigation
Sophisticated replay with slight phase variationFNV-1a uses 1% quantization; small perturbations change the hashAdd temporal correlation checks (consecutive frame deltas)
Man-in-the-middle on the WiFi channelModules analyze CSI content, not channel authenticationUse WPA3 encryption + MAC filtering
Physical obstruction (blocking line-of-sight)Looks like a person leaving, not an attackCross-reference with PIR sensors
Slow amplitude drift (gradual injection)Below the 10x threshold per frameAdd longer-term amplitude trend monitoring
Firmware tamperingModules run in WASM sandbox, cannot detect host compromiseSecure boot + signed firmware (ADR-032)

Deployment Recommendations

  1. Always run both modules together: Signal Shield catches active attacks, Behavioral Profiler catches passive anomalies.
  2. Allow full calibration: Signal Shield needs 100 frames (5 seconds) for SNR baseline. Behavioral Profiler needs 1000 frames (~50 seconds) for reliable Z-scores.
  3. Combine with Temporal Logic Guard (tmp_temporal_logic_guard.rs): Its safety invariants catch impossible state combinations (e.g., "fall alert when room is empty") that indicate sensor manipulation.
  4. Connect to the Self-Healing Mesh (aut_self_healing_mesh.rs): If a node in the mesh is being jammed, the mesh can automatically reconfigure around the compromised node.

Memory Layout

ModuleState Size (approx)Static Event Buffer
Signal Shield~420 bytes (64 hashes + 32 prev_amps + calibration)4 entries
Behavioral Profiler~2.4 KB (200-entry observation window + 6 Welford stats)4 entries

Both modules use fixed-size arrays and static event buffers. No heap allocation. Fully no_std compliant.