Skip to main content

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

During my internship at Oberon microsystems AG I implemented a C# wrapper for NaCl and integrated it with Microsoft .NET and the Microsoft .NET Micro Framework. The technology preview is available on the webpage of the mountaineer group.

Benchmarks #

On a MountaineerEth mainboard we were able to decrypt and encrypt a message in 154ms!

NaCl CryptoBox encrypt and CryptoSign signing.

Hardware #

The MountaineerEth mainboard has a STM32F4 processor which runs on a 168Mhz clock rate, with 192kB RAM and possesses 1MB of Flash storage.

Due to these hardware constraints it’s impossible to integrate a crypto library like OpenSSL on these devices.

MountaineerEth mainboard

The chip also contains a hardware random number generator which is also exposed as a library on NETMF.

Using the Library #

The library is a straightforward implementation of DJBs code and allows a direct translation of C code to C#:

CryptoBox.Box(encryptedData, 0, unencryptedData, 0, unencryptedData.Length, nonce, publicKey, secretKey);

The library verifies the preconditions of the input and requires C style padding in order to work. This means that before data can be encrypted or decrypted padding needs to be added to the input (sample from here):

// Encrypting a message using private/public key encryption
static byte[] Encrypt(string message, byte[] publicKey, byte[] secretKey, byte[] nonce)
{
    // First convert the string to a byte array:
    byte[] messageBuffer = UTF8Encoding.UTF8.GetBytes(message);
    // Preallocate array and accomodate space for zero padding.
    var unencryptedData = new byte[CryptoBox.ZeroBytes + messageBuffer.Length];
    Array.Copy(messageBuffer, 0, unencryptedData, CryptoBox.ZeroBytes, messageBuffer.Length);
    // Preallocate output buffer
    var encryptedData = new byte[unencryptedData.Length];
    CryptoBox.Box(encryptedData, 0, unencryptedData, 0, unencryptedData.Length, nonce, publicKey, secretKey);
    return encryptedData; // Padding was not removed
}

CryptoBox.Open requires a padding of CryptoBox.ZeroBytes in the message buffer to encrypt data. The encryptedData array also contains a buffer of CryptoBox.BoxZeroBytes padding which we don’t remove in the sample above.

Similarly to decrypt data. We already assume that the encryptedData array contains CryptoBox.BoxZeroBytes padding:

// Decrypts a encrypted string using private/public key encryption
static string Decrypt(byte[] encryptedData, byte[] publicKey, byte[] secretKey, byte[] nonce)
{
    // First preallocate the data array
    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");
    }

    // Message could be decrypted, convert byte array to string
    int dataLength = (decryptedData.Length - CryptoBox.ZeroBytes);
    char[] buffer = UTF8Encoding.UTF8.GetChars(decryptedData, CryptoBox.ZeroBytes, dataLength);
    return new string(buffer);
}

Oberon microsystems AG #

Oberon microsystems AG is a small company in Zürich, Switzerland that develops both hardware and software for internet of things.

Oberon GSM BLE Gateway