Skip to main content

NaCl on the Microsoft .NET and Microsoft .NET Micro Framework

Table of Contents
Lightweight Cryptography for Embedded .NET Devices: NaCl meets the .NET Micro Framework.

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.

Benchmark: NaCl CryptoBox encryption and CryptoSign signing

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.

MountaineerEth mainboard

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.

Oberon GSM BLE Gateway