Client side encryption performance – Raspberry Pi

IQrypt is designed to be used at client side, more specifically directly on client mobile/desktop devices, so every encryption/decryption operation is executed by the device itself. Performance is a critical aspect of any application and we are asked often: “what about performance?”. We designed IQrypt with performance in mind and we did a lot of testing regarding performance at the very early stage of the product to be sure the product is practical and it can be embedded into any application even it runs on devices with modest specs.

Today we are showing you some performance tests results made on a Rasberry Pi 2 Model B which has 900MHz quad-core ARM CPU and 1 GB of RAM and which looks like this:

Pi2ModB1GB_-comp

As operating system, we used latest Windows 10 IoT Core (version 10.0.14295.1000) and latest IQrypt SDK for .NET that can be found on Github.

We will encrypt/decrypt 1000 and respectively 10000 objects and we will measure the time elapsed to execute those operations. IQrypt SDK for .NET, before encryption, it serialize objects to JSON and after decryption it deserialize back to objects so we will measure the time elapsed first for serialization and then for serialization + encryption to be able to extract the time elapsed for encryption only (similar for decryption and deserialization).

We will follow our best-practice model, so let’s define an entity type first:

    public class Patient
    {

        public string ObjectId { get; set; }
        public string SSN { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Gender { get; set; }
        public string Location { get; set; }
        public string Building { get; set; }
        public int Floor { get; set; }
        public DateTime AgendaTime { get; set; }
        public string Treatment { get; set; }
        public string Status { get; set; }
        public string Doctor { get; set; }
        public string Version { get; set; }
        public bool IsVisited { get; set; }
       
    }

 

Then the Document entity which has Content + Tags:

        public class Document
        {
            public string Content;
            public Dictionary<string, string> Tags;
        }

Now let’s create a method to generate a Patient entity :

        private Random rnd = new Random();
        private Patient GeneratePatient()
        {
            Patient p = new Patient();
            p.ObjectId = rnd.Next().ToString();
            p.FirstName = "John"+rnd.Next();
            p.LastName = "Smith" + rnd.Next();
            p.SSN = "721-07-" + rnd.Next(1111, 9999);
            p.AgendaTime = DateTime.Now.Date;
            p.Doctor = "Dr. Joe Peterson";
            p.Treatment = "Lorem ipsum....";
            p.Status = "stable";
            p.Building = "A";
            p.Floor = 1;
            return p;
            
        }

We will encrypt entire Patient object with RND encryption scheme and we’ll extract two tags: SSN (social security number) and AgendaTime.

We will create 2 methods, one that creates and serializes/deserialize 1000/10000 documents and one that serialize/deserialize + encrypt/decrypt those objects.

        private void SerializeOnly()
        {

            var stopwatch = new Stopwatch();
            listBox.Items.Clear();
            listBox.Items.Add("Serialize documents started...");
            //warm-up
            Patient pw = this.GeneratePatient();
            string serializedPatientw= JsonConvert.SerializeObject(pw);
            string serializedSSNTagw = JsonConvert.SerializeObject(pw.SSN);
            string serializedAgendaTimeTagw = JsonConvert.SerializeObject(pw.AgendaTime);

            stopwatch.Start();
            List documents = new List();
            for (int i = 0; i < 1000; i++)
            {
                Patient p = this.GeneratePatient();
                string serializedPatient = JsonConvert.SerializeObject(p);
                string serializedSSNTag = JsonConvert.SerializeObject(p.SSN);
                string serializedAgendaTimeTag = JsonConvert.SerializeObject(p.AgendaTime);
                Document doc = new Document();
                doc.Content = serializedPatient;
                doc.Tags = new Dictionary<string, string>();
                doc.Tags.Add("SSN", serializedSSNTag);
                doc.Tags.Add("AgendaTime", serializedAgendaTimeTag);
                documents.Add(doc);
            }
            stopwatch.Stop();
            listBox.Items.Add("Serializing documents took:" + stopwatch.Elapsed);

            listBox.Items.Add("Deserializing documents started...");
            stopwatch.Start();
            foreach (Document d in documents)
            {
                Patient p = (Patient)JsonConvert.DeserializeObject(d.Content, typeof(Patient));
                string ssnDeserialized= (string)JsonConvert.DeserializeObject(d.Tags["SSN"], typeof(string));
                DateTime agendaTimeDeserialized = (DateTime)JsonConvert.DeserializeObject(d.Tags["AgendaTime"], typeof(DateTime));
            }
            stopwatch.Stop();
            listBox.Items.Add("Deserializing documents took:" + stopwatch.Elapsed);
            
        }

And now also encrypt them (IQrypt serialize/deserialize objects internally):

        private void SerializeAndEncrypt()
        {
            listBox.Items.Clear();
           
            IQrypt.IQryptConfigurator.SetEncryptionChiper(IQrypt.Cipher.AES256, "mysuper_secret");
            var encryptorRND = IQrypt.EncryptorFactory.GetEncryptor(IQrypt.EncryptionType.RND);
            var encryptorDET = IQrypt.EncryptorFactory.GetEncryptor(IQrypt.EncryptionType.DET);
            var encryptorOPE = IQrypt.EncryptorFactory.GetEncryptor(IQrypt.EncryptionType.OPE);
          
            //warm-up 
            Patient pw = this.GeneratePatient();
            string encryptedPatientw = encryptorRND.Encrypt(pw);
            string encryptedSSNTagw = encryptorDET.Encrypt(pw.SSN);
            string encryptedAgendaTimeTagw = encryptorOPE.Encrypt(pw.AgendaTime);

            listBox.Items.Add("Encrypt documents started...");
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            List documents = new List();
            for (int i = 0; i < 1000; i++)
            {
                Patient p = this.GeneratePatient();
                string encryptedPatient = encryptorRND.Encrypt(p);
                string encryptedSSNTag = encryptorDET.Encrypt(p.SSN);
                string encryptedAgendaTimeTag = encryptorOPE.Encrypt(p.AgendaTime);
                Document doc = new Document();
                doc.Content = encryptedPatient;
                doc.Tags = new Dictionary<string, string>();
                doc.Tags.Add("SSN", encryptedSSNTag);
                doc.Tags.Add("AgendaTime", encryptedAgendaTimeTag);
                documents.Add(doc);
            }
            stopwatch.Stop();
            listBox.Items.Add("Encrypting documents took:" + stopwatch.Elapsed);

            listBox.Items.Add("Decrypt documents started...");
            stopwatch.Start();
            foreach (Document d in documents)
            {
                Patient p = (Patient)encryptorRND.Decrypt(d.Content, typeof(Patient));
                string ssnDecrypted = (string)encryptorDET.Decrypt(d.Tags["SSN"], typeof(string));
                DateTime agendaTimeDecrypted = (DateTime)encryptorOPE.Decrypt(d.Tags["AgendaTime"], typeof(DateTime));
            }
            stopwatch.Stop();
            listBox.Items.Add("Decrypting documents took:" + stopwatch.Elapsed);

          
        }

 

The above methods are called in a Universal Windows App and executed on the Raspberry Pi device, here are the results:

Encrypting:

Nr.Objects Serialize(ms) Encrypt+Serialize(ms) Encryption(ms) Avg per object(ms)
1000 677 3289 2612 2.612
10000 6069 19040 12971 1.2971

Decrypting:

Nr.Objects Deserialize(ms) Decrypt+deserialize(ms) Decryption(ms) Avg per object(ms)
1000 2366 4643 2277 2.277
10000 15186 33099 17913 1.7913

So if we encrypt 1000 objects, it took 2612 milliseconds (col4= col3-col2) just for the encryption operation, so an average of 2.6 milliseconds per object. If we encrypt 10000 objects the average is even lower 1.29 milliseconds per object.
Similar for decryption, the average time for decrypting an object is 2.27 milliseconds when we decrypt 1000 objects and 1.79 ms when we decrypt 10000 objects.

Despite the fact that Raspberry Pi has modest specs comparing with many other mobile phones/devices nowadays, IQrypt overhead is between 1 and 3 milliseconds per object/document which is really ignorable comparing with network latency and other factors which influence the performance of an application.