19.03.2025, 18:15
Learn how DMX frame encryption was tested on the rp2350 embedded system using libHydrogen. Discover the experiment's setup, performance insights, and why securing lighting protocols like Art-Net and sACN is crucial for modern applications.
During this year's PlugFest in Lille, the question arose on how to secure lighting protocols like Art-Net, or sACN. In order to answer that, in this post we take a quick peek at how costly state of the art encryption on an embedded system actually is.
We dive into an experiment designed to test the feasibility of encrypting DMX frames on a resource-constrained embedded system – in this case, the rp2350. We leveraged libHydrogen for encryption and ran tests to benchmark both encryption and decryption times.
The device used for testing is the QubiCast Art-Net / sACN Node prototype running QubiCore, based on a rp2350 running at 200MHz.
The core goal of this experiment was to verify that DMX frame encryption could be effectively implemented on the rp2350. Securing DMX frames is critical when working in environments where integrity and confidentiality are a concern. Using libHydrogen’s secret box API, we set up a basic test scenario:
Let’s break down the code snippet:
if (hydro_init() != 0) {
printf("Failed to initialize libhydrogen.\n");
return -1;
}
static constexpr uint16_t PLAINTEXT_SIZE = 513;
static constexpr std::size_t ITERATIONS = 1000;
static const std::string context = "QUBICORE";
std::array<uint8_t, PLAINTEXT_SIZE> plaintext{};
for (std::size_t i = 0; i < PLAINTEXT_SIZE; ++i) {
plaintext[i] = static_cast<uint8_t>(i);
}
std::array<uint8_t, hydro_secretbox_KEYBYTES> key{};
std::array<uint8_t, PLAINTEXT_SIZE + hydro_secretbox_HEADERBYTES> ciphertext{};
hydro_secretbox_keygen(key.data());
hydro_secretbox_keygen()
.const uint64_t tStartEncrypt = get_absolute_time();
for(int i = 0; i < ITERATIONS; i++)
hydro_secretbox_encrypt(ciphertext.data(), plaintext.data(), sizeof(plaintext), 0, context.c_str(), key.data());
const uint64_t tEndEncrypt = get_absolute_time();
const uint64_t diffEncrypt = (tEndEncrypt - tStartEncrypt);
const uint64_t meanEncrypt = diffEncrypt / ITERATIONS;
The same was done for the decryption, using
hydro_secretbox_decrypt(decrypted.data(), ciphertext.data(), sizeof(ciphertext), 0, context.c_str(), key.data());
instead of the encryption method shown above.
if (std::equal(plaintext.begin(), plaintext.end(), decrypted.begin())) {
printf("Decryption successful: plaintext matches.\n");
} else {
printf("Decryption error: plaintext does not match.\n");
}
printf("Results: Encryption mean: %u; Decryption mean: %u ", meanEncrypt, meanDecrypt);
The performance numbers from our experiment suggest that DMX frame encryption using libHydrogen is viable on embedded systems like the rp2350:
This experiment opens up opportunities for securing lighting control systems and similar DMX applications in environments where both performance and security are paramount. Especially ArtAddress / ArtRdm / ArtDmx and sACN might profit from an added layer of encryption to ensure confidentiality and make sure the data isn't tampered with.
Happy coding and secure lighting!
Philipp
Subscribe to our newsletter for exclusive insights and offers. Illuminate your expertise!
Explore other posts