NaCl on the Microsoft .NET and Microsoft .NET Micro Framework
Table of Contents
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!
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.
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.