Flume Water Monitor 915 MHz Signal Security – It’s Not Bad


The Flume Water Monitor is a widely used consumer device that attaches to a home’s water meter and transmits near-real-time usage data to a companion bridge device on the home Wi-Fi network. The bridge then uploads the data to the cloud, where it is accessible via the Flume app. The water-meter-sensor–><–bridge link uses a 915 MHz band RF signal. This link is encrypted, and I was able to defeat the encryption with a few weeks of part-time effort, aided by the reverse-engineering work published by Steve Crosby [1]. Here’s a brief summary of what I did.

Finding and Demodulating the 915 MHz Band RF Signal

FCC documentation indicates the device uses a 50-channel frequency-hopping approach in the 902.5–927 MHz band, with 500 kHz channel separation. I tuned my LimeSDR Mini Software Defined Radio to the center of the band (using a 20 MHz display bandwidth) and turned on the faucet. Short-duration (~1 ms) signals with ~500 kHz bandwidth were readily visible, as shown below.

Example Frequency Spectrum of Flume RF Message (909 MHz center frequency) Example Frequency Spectrum of Flume RF Message (909 MHz center frequency)

After some experimentation, I determined that the signal uses 2-FSK (Frequency Shift Keying) modulation at 200 kbps[2], with a portion of the ~25-byte messages whitened using an option in the sensor’s RFM69 transmitter chip. Side note: the whitening sequence is poorly documented, but I believe it begins with FF 87 B8 89… (see [3] for full sequence).

The message structure is straightforward:

Message Format

I validated the Cyclical Redundancy Check CRC-16 values using the generator polynomial 0x1021 (per the chipset documentation) with an initial seed of 0x1D0F (not documented) and a final bit reversal of the CRC output.

What About the Encrypted Payload?

The 16-byte payload is encrypted in AES-128 Electronic Codebook (ECB) mode (another RFM69 chipset option). According to the raw data in Crosby’s post, the 128-bit key is derived from an 8-byte key using a simple hardcoded mapping. While 64 bits is still too large to brute-force directly, it turns out that a subset of the RF message header bytes (not encrypted) provide another 16 bits of the key. This reduces the search space to 48 bits. Adding the assumption (inferred from Crosby’s data) that half of the key’s last byte is a known constant further reduces it to 44 bits.

I brute-forced the remaining 44 unknown bits by testing multiple messages and looking for consistently low-entropy plaintext (or plaintexts with a high number of matching bits). An unoptimized Python script on a decent GPU took roughly one day (<$10 on a cloud platform).

Wrapping It Up

For a consumer water sensor, a frequency-hopping waveform combined with 44-bit effective encryption on the payload is not an unreasonable level of security. That said, there is still some risk: with knowledge of the AES key, CRC algorithm, and other parameters, it becomes possible to generate spoofed messages. These could potentially enable malicious firmware updates if over-the-air (OTA) updates are supported (I have not investigated this and do not plan to).

I reached out to Flume. They were very responsive, and their CTO shared an overview of their already-in-progress plans to further improve the product’s privacy and security.

[1] (https://lithostech.com/2024/12/diving-into-flume-water-monitor/)

[2] other signals with different data rates were also observed (e.g. upon bridge reboot)

[3] (https://www.nxp.com/docs/en/application-note/AN5070.pdf)