In the Internet-of-Things world there are certain applications that produce very low volume communications. For example reading a water meter once every hour comes to mind. If the reading could be encoded as a 32 bit unsigned integer and adding a 24 bit serial number this device would transmit only about 614 KBytes of data over an assumed life-time of 10 years (7 bytes * 24 hours * 365 days * 10 years).
I'd like to put for discussion whether a One-Time-Pad (OTP) solution plus HMAC could be a viable solution in this scenario. A key stream of 614 KBytes could be easily pre-generated and stored on the device, although a Hardware Security Module (HSM) implementing "OTP + HMAC" probably does not yet exist.
I am aware of the core problems of using One-Time-Pads in practice. Assuming that these challenges could be overcome (at least in a manner that is sufficiently secure for the purpose of transmitting water meter readings once every hour) the following pseudo-code explains the approach.
# KEYSTREAM is a file containing at least 614 KBytes of random bytes.
# COUNTER is the current offset into KEYSTREAM.
function encrypt_and_hmac(plaintext):
fp = open(KEYSTREAM)
fp.seek(COUNTER)
# Remember the current offset into the KEYSTREAM
pos = fp.pos()
# Read bytes from KEYSTREAM for encrypting the plaintext
cipherpad = fp.read(len(plaintext))
ciphertext = plaintext XOR cipherpad
# Read 8 bytes (in this example) from KEYSTREAM for HMAC
macpad = fp.read(8)
hmac = hash(ciphertext + macpad)
# Safely(!) erase the used bytes from the KEYSTRAM
erase(KEYSTREAM, pos, pos+len(plaintext)+8)
return pos, ciphertext, hmac
The current offset into the key stream (pos), the ciphertext and HMAC can now be transmitted. Decryption and verification would work like this.
function decrypt_and_verify(pos, ciphertext, hmac):
fp = open(KEYSTREAM)
fp.seek(pos)
cipherpad = fp.read(len(plaintext))
macpad = fp.read(8)
assert hash(ciphertext + macpad) == hmac
plaintext = ciphertext XOR cipherpad
return plaintext
Just to preempt some potential comments:
- Yes, AES-EAX and the like may be a better solution.
- The challenge of safely distributing the KEYSTREAM is no different from using any other shared secret unless a Key-Exchange Protocol is used.
- Ideally the Encrypt-and-HMAC should be done inside an HSM module or the security could be easily compromised if someone gains access to the water meter.
- Having a small number of compromised water meters may be an acceptable business risk akin to water meters that are simply faulty. This would eliminate the cost of the HSM module.
- An interesting challenge arises if the payload size of the transmission channel is very small like in Sigfox (12 bytes) and the smaller packet size options of LoRaWan and Weightless. Could one transmit only the first few bytes of the HMAC???
I am looking forward to your comments, feedback and criticism.