Skip to content

Je1al/SecureIoT-Protocol

Repository files navigation

SecureIoT-Protocol

CI License: MIT C++17 Standards

A compact, dependency-free secure-channel protocol for IoT, implemented in modern C++17. It gives two devices that share a pre-shared key a mutually authenticated, encrypted, replay-protected channel with forward secrecy — built on cryptographic primitives written from scratch and validated against the official RFC/NIST test vectors.

Why it exists. Constrained IoT links often ship with home-grown "encryption" (XOR, custom hashes) that collapses under a real attacker. SecureIoT shows how to do it properly with standardized primitives and an auditable protocol — and backs the design with tests, fuzzing, sanitizers, a threat model, and a wire specification.


Highlights

  • 🔐 Real, standardized cryptography, from scratch — SHA-256, HMAC, HKDF, ChaCha20-Poly1305 AEAD, and X25519, each checked against its RFC/FIPS test vectors (no OpenSSL, no libsodium — zero third-party dependencies).
  • 🤝 Mutually authenticated handshake — 3 messages, ephemeral X25519 + PSK, with a TLS-1.3-style HKDF key schedule and transcript-bound Finished MACs.
  • Forward secrecy — ephemeral keys are generated per handshake and wiped; a later PSK leak does not expose past sessions.
  • 🛡️ AEAD record layer — ChaCha20-Poly1305 with the record header authenticated as associated data and a TLS-1.3-style per-record nonce.
  • 🔁 Anti-replay — per-record sequence numbers plus a 64-entry IPsec-style sliding window that tolerates reordering but rejects replays and stale packets.
  • 🌐 Transport-agnostic — runs over the provided TCP demo, or any datagram / serial / LoRa transport that delivers whole messages.
  • Engineered like production code — 37 unit/integration tests, libFuzzer harnesses, ASan/UBSan-clean, CMake + Make builds, and CI on Linux and macOS.

Security properties

Property How it is achieved
Confidentiality ChaCha20-Poly1305 AEAD per record (RFC 8439)
Integrity / tamper Poly1305 tag over header + ciphertext; verify-before-release
Mutual authentication PSK mixed into the key schedule + Finished MACs in both directions
Forward secrecy Ephemeral X25519 key agreement (RFC 7748), private keys wiped
Replay protection Sequence numbers + 64-entry sliding window (RFC 4303 style)
Transcript integrity SHA-256 transcript hash bound into both Finished MACs

See the threat model for the attacker model, the full attack/defense matrix, and the explicit assumptions and limitations.


Quick start

git clone https://github.com/Je1al/SecureIoT-Protocol.git
cd SecureIoT-Protocol

make            # build the static library + tools
make test       # run the full test suite (RFC vectors + attack scenarios)
make demo       # in-process end-to-end demonstration
make bench      # micro-benchmarks

CMake is also supported:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build --output-on-failure

In-process demo

make demo runs a complete handshake, encrypts a record, and then shows the three core attacks being rejected:

=== Handshake (ephemeral X25519 + PSK authentication) ===
-> ClientHello   (65 bytes)
<- ServerHello   (97 bytes)
-> ClientFinished(32 bytes)
Handshake complete. device.established=1 gateway.established=1

=== Secured record (ChaCha20-Poly1305) ===
plaintext : temperature=22.5C;humidity=41%
record    : 170000000000000000001e82267dd51c45ec6693...
decrypted : temperature=22.5C;humidity=41%

=== Attack rejections ===
replay        -> rejected
tampered byte -> rejected
injected junk -> rejected
next genuine  -> accepted: status=ok

Networked demo (real TCP)

Terminal 1 — gateway:

./build/secure_server --port 9009 --passphrase "field-key-42"

Terminal 2 — device (the --replay flag re-sends a captured record to prove the server rejects it):

./build/secure_client --port 9009 --passphrase "field-key-42" --count 3 --replay
# server
[server] handshake OK; session established
[server] telemetry #1: reading[0]=temperature=20C
[server] telemetry #2: reading[1]=temperature=21C
[server] telemetry #3: reading[2]=temperature=22C
[server] record REJECTED (replay/tamper/forgery)

How the protocol works

 Initiator (device)                          Responder (gateway)
        |  ClientHello  (version, c_random, c_eph_pub)  |
        | -------------------------------------------> |
        |  ServerHello  (version, s_random, s_eph_pub,  |
        |                server_finished)              |
        | <------------------------------------------- |
        |  ClientFinished (client_finished)            |
        | -------------------------------------------> |
        |        application records (both ways)       |
        | <==========================================> |

Key schedule (computed identically on both sides):

dh   = X25519(my_eph_priv, peer_eph_pub)
th   = SHA-256("SecureIoT/1" || c_random || c_eph_pub || s_random || s_eph_pub)
prk  = HKDF-Extract(salt = PSK, ikm = dh)        # PSK ⇒ auth, dh ⇒ forward secrecy
k_i2r, k_r2i, iv_i2r, iv_r2i = HKDF-Expand(prk, "secure-iot v1 traffic keys", 88)

The full byte-level wire format, nonce construction, and receive-side processing are specified in docs/PROTOCOL.md.

Library API

#include "secure_iot/protocol/session.h"
using namespace secure_iot;

Session::Psk psk = /* 32 bytes, provisioned out of band */;

Session device(Role::kInitiator, psk);
Session gateway(Role::kResponder, psk);

// Handshake (exchange these byte buffers over any transport)
auto m1 = device.client_hello();
auto m2 = gateway.process_client_hello(m1);
auto m3 = device.process_server_hello(m2);   // verifies the gateway
gateway.process_client_finished(m3);          // verifies the device

// Secure messaging
auto record   = device.seal({'h','e','l','l','o'});
auto plaintext = gateway.open(record);        // std::optional; empty if rejected

Project layout

include/secure_iot/   Public API
  crypto/             sha256, hmac_sha256, hkdf, chacha20, poly1305, aead, x25519, random
  protocol/           config, replay_window, session
  util/               bytes (endian), ct (constant-time), serial (safe parsing)
src/                  Implementations
tools/                offline_demo, secure_server, secure_client, benchmark
tests/                Unit tests + RFC/NIST vectors + attack scenarios
fuzz/                 libFuzzer harnesses for the parsers
docs/                 PROTOCOL.md, THREAT_MODEL.md, ARCHITECTURE.md

See docs/ARCHITECTURE.md for the layering and design decisions.

Testing, fuzzing, sanitizers

make test                       # 37 test cases: RFC/NIST vectors + protocol scenarios

# AddressSanitizer + UndefinedBehaviorSanitizer
cmake -S . -B build-asan -DSECUREIOT_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build build-asan && ctest --test-dir build-asan --output-on-failure

# Coverage-guided fuzzing of the wire parsers (Clang)
make fuzz CXX=clang++
./build/fuzz_handshake -max_total_time=60
./build/fuzz_record    -max_total_time=60

Every primitive is checked against the published vectors of its standard (SHA-256 → FIPS 180-4; HMAC/HKDF → RFC 4231/5869; ChaCha20-Poly1305 → RFC 8439; X25519 → RFC 7748), and the protocol is checked end-to-end against replay, tampering, injection, and wrong-PSK attacks.

Roadmap

  • Optional certificate / Ed25519-signature authentication alongside the PSK
  • 0-RTT early data for reconnecting devices
  • no_std-style embedded build profile (no heap, fixed buffers)
  • Formal model of the handshake (Tamarin / ProVerif)

Security status

The cryptography is standardized and validated against official test vectors, but this is an independent implementation that has not been formally audited. For production, prefer a vetted library such as libsodium. See SECURITY.md for details and how to report issues.

License

Released under the MIT License.

About

Secure-channel protocol for IoT in C++17: mutually authenticated handshake (ephemeral X25519 + PSK), ChaCha20-Poly1305 record layer, HKDF key schedule, and sliding-window anti-replay — crypto implemented from scratch and validated against RFC test vectors.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors