sig-net 0.5.2

Sig-Net secure CoAP-based DMX512 lighting control protocol library
Documentation

crates.io docs.rs MIT licensed Rust 1.75+

Sig-Net Protocol Framework

sĭg nĕt

Sig-Net is a secure, multicast-based protocol for DMX512 entertainment lighting control built on CoAP (RFC 7252). It provides authenticated packet delivery via HMAC-SHA256, key derivation via HKDF, and anti-replay protection — all in a lightweight UDP multicast package.

This is a pure Rust implementation of the Sig-Net Protocol Framework specification, ported from the original C++ SDK with zero unsafe code.

Repository Packages

Package crates.io Docs Description
sig-net (this crate) crates.io docs.rs Core library — types, crypto, CoAP, TLV, parsing, UDP
signet-ffi C-compatible FFI bindings (staticlib + cdylib + cbindgen header)

Quick Start

[dependencies]
sig-net = "0.5"

Build and send a DMX level packet:

use sig_net::*;

let mut k0 = [0u8; 32];
crypto::derive_k0_from_passphrase(b"Ge2p$E$4*A", &mut k0)?;

let mut sender_key = [0u8; 32];
crypto::derive_sender_key(&k0, &mut sender_key)?;

let tuid = TUID::from_hex(b"534C00000001")?;
let dmx: Vec<u8> = (0..512).map(|i| (i * 4) as u8).collect();

let mut buf = PacketBuffer::new();
send::build_dmx_packet(&mut buf, 1, &dmx, &tuid.0, 0, 0x0000, 1, 1, &sender_key, 1)?;

Feature Flags

[dependencies]
sig-net = { version = "0.5", default-features = false }       # core types (zero deps)
sig-net = { version = "0.5", features = ["crypto"] }          # + HMAC/HKDF/PBKDF2/passphrase
sig-net = { version = "0.5", features = ["crypto", "net"] }   # + UDP multicast (default)

API Overview

Core Types

let header = CoAPHeader::new(42);
let mut buf = PacketBuffer::new();
let tuid = TUID::from_hex(b"534C00000001")?;
let addr = calculate_multicast_address(1)?;

Cryptography (sig_net::crypto)

crypto::hmac_sha256(key, data, &mut hmac)?;
crypto::hkdf_expand(prk, info, &mut okm)?;
crypto::derive_k0_from_passphrase(pw, &mut k0)?;
crypto::derive_sender_key(&k0, &mut ks)?;
crypto::validate_passphrase(b"Ge2p$E$4*A")?;
crypto::verify_packet_hmac(uri, &options, payload, &key)?;

Protocol Building

coap::build_coap_header(&mut buf, message_id)?;
tlv::encode_tid_level(&mut buf, &dmx_data)?;
send::build_dmx_packet(&mut buf, 1, &dmx, &tuid, 0, ...)?;
send::build_announce_packet(&mut buf, &tuid, ...)?;
send::build_poll_packet(&mut buf, &mgr_tuid, ...)?;

Protocol Parsing

let mut reader = parse::PacketReader::new(packet, packet_len);
let header = reader.parse_coap_header()?;
let options = reader.parse_signet_options()?;
let tlv = reader.parse_tlv_block()?;
let slots = parse::parse_tid_level(&tlv, &mut dmx)?;

UDP Multicast

let socket = net::UdpMulticastSocket::bind(5683)?;
socket.join_multicast_group(Ipv4Addr::new(239, 254, 0, 1), None)?;
socket.send_multicast(packet, 1)?;
let (n, src) = socket.recv_from(&mut rx_buf)?;

C / C++ FFI

See signet-ffi.

#include "signet.h"

uint8_t k0[32];
signet_derive_k0_from_passphrase("Ge2p$E$4*A", 10, k0);

uint8_t sender_key[32];
signet_derive_sender_key(k0, sender_key);

Examples

Example Location Run
Core types examples/rust/core.rs cargo run -p sig-net --example core
Cryptography examples/rust/crypto.rs cargo run -p sig-net --example crypto
Full protocol examples/rust/full.rs cargo run -p sig-net --example full
C++ FFI demo examples/signet-ffi/ffi-demo.cpp make -C examples/signet-ffi run

Test Vectors

Test Status Details
RFC 4231 TC1 Key=20×0x0B, Data="Hi There", HMAC=B0344C61...
RFC 4231 TC2 Key="Jefe", Data="what do ya want...", HMAC=5BDCC146...
PBKDF2 K0 100k iterations, "Ge2p$E$4*A" → K0=52FCC2E7...

Crate Structure

crates/
├── sig-net/          ← main library
│   ├── src/
│   │   ├── constants  protocol constants (TIDs, option numbers, crypto params)
│   │   ├── types      CoAPHeader, PacketBuffer, TUID, SigNetOptions
│   │   ├── crypto     HMAC-SHA256, HKDF, PBKDF2, key derivation, passphrase
│   │   ├── coap       CoAP header/option encoding, URI building
│   │   ├── tlv        TLV payload encoding
│   │   ├── security   SigNet custom options, HMAC input/output
│   │   ├── send       DMX packet, announce, poll packet builders
│   │   ├── parse      PacketReader, CoAP/TLV parsing, HMAC verification
│   │   └── net        UDP multicast (socket2)
│   └── tests/
│       └── integration.rs  24 integration tests
└── signet-ffi/        ← C-compatible FFI (see [README](../signet-ffi/README.md))
examples/
├── rust/              ← Rust examples (core, crypto, full)
└── signet-ffi/        ← C++ FFI demo (ffi-demo.cpp + Makefile)

Differences from the C++ SDK

Area C++ SDK sig-net (Rust)
Platform Windows-only (BCrypt, Winsock2) Cross-platform (Linux, macOS, Windows)
Random generation BCryptGenRandom getrandom crate
Unsafe code N/A (C++) Zero unsafe in the library; FFI layer only in signet-ffi
Error type int32_t return codes Result<T, SigNetError>
Passphrase generation strategy Single-pass construction; calls ValidatePassphrase at the end; falls back to hardcoded "Abc123!@#$" if validation fails Retry loop up to 100 random attempts; calls analyse_passphrase after each attempt; returns Err(Crypto) if all attempts fail
Passphrase validation — sequential check HasSequentialRun checks both ascending (abcd) and descending (dcba) runs of 4+ characters Same — analyse_passphrase checks both directions, matching C++ exactly
HMAC input Covers full TLV payload: [TID][Length][Value] Same — HMAC covers the complete TLV-encoded payload, not the raw DMX bytes
Sequence wrap-around 0xFFFFFFFF1 (skips 0, which is reserved for "no sequence") Same — increment_sequence mirrors this behaviour

Note on passphrase generation. The C++ fallback to "Abc123!@#$" means that under adversarial entropy conditions every caller receives the same passphrase. The Rust implementation avoids this by retrying with fresh random bytes instead of falling back to a constant.

Safety

Zero unsafe blocks in the entire sig-net library:

  • CoAP header uses manual bit-shifting instead of #[repr(packed)]
  • Network I/O uses the socket2 crate (safe abstraction over Winsock/BSD sockets)
  • Constant-time HMAC comparison uses the subtle crate

License

Sig-Net is free and open-source software licensed under the MIT License.