During my internship at Oberon microsystems AG, I developed a C# wrapper for NaCl, a high-speed cryptographic library by Daniel J. Bernstein. The wrapper integrates NaCl with both Microsoft .NET and the .NET Micro Framework (NETMF), enabling secure encryption on resource-constrained embedded devices.
The project culminated in a technology preview, available via the Mountaineer Group.
Real-World Performance #
Running on a MountaineerEth mainboard, we achieved real-time encryption and decryption in 154ms per message — impressive given the hardware limitations.
Platform Constraints #
The MountaineerEth board is powered by an STM32F4 microcontroller running at 168 MHz, with 192 kB RAM and 1 MB flash. These limitations make libraries like OpenSSL impractical, but NaCl’s lightweight design fits perfectly — especially when paired with NETMF.
Additionally, the microcontroller features a hardware random number generator, which we exposed through a dedicated NETMF library to support cryptographic needs.
Using the Library #
The C# wrapper is a direct, low-level translation of NaCl’s C implementation. It includes strict input validation and supports public-key authenticated encryption (via CryptoBox
) and decryption (via CryptoBox.Open
). Padding requirements from the original C implementation are preserved.
Encryption Example:
static byte[] Encrypt(string message, byte[] publicKey, byte[] secretKey, byte[] nonce)
{
byte[] messageBuffer = UTF8Encoding.UTF8.GetBytes(message);
var unencryptedData = new byte[CryptoBox.ZeroBytes + messageBuffer.Length];
Array.Copy(messageBuffer, 0, unencryptedData, CryptoBox.ZeroBytes, messageBuffer.Length);
var encryptedData = new byte[unencryptedData.Length];
CryptoBox.Box(encryptedData, 0, unencryptedData, 0, unencryptedData.Length, nonce, publicKey, secretKey);
return encryptedData;
}
Decryption Example:
static string Decrypt(byte[] encryptedData, byte[] publicKey, byte[] secretKey, byte[] nonce)
{
var decryptedData = new byte[encryptedData.Length];
if (CryptoBox.Open(decryptedData, 0, encryptedData, 0, encryptedData.Length, nonce, publicKey, secretKey) != 0)
{
throw new ArgumentException("Could not decrypt data");
}
int dataLength = decryptedData.Length - CryptoBox.ZeroBytes;
char[] buffer = UTF8Encoding.UTF8.GetChars(decryptedData, CryptoBox.ZeroBytes, dataLength);
return new string(buffer);
}
Padding conventions from NaCl (ZeroBytes
, BoxZeroBytes
) are handled manually as shown above.
About Oberon microsystems AG #
Oberon microsystems AG is a Zürich-based company specializing in embedded software and hardware for the Internet of Things. Their Mountaineer platform supports NETMF and provides reference designs for secure, low-power connected devices.
