Grypto-Grid Solution to Digital Signatures

Introduction:

Grid computing has become necessary with increase in need for computing power. Grid computing primarily allows us to delegate the processing to idle nodes. Several embarrassingly parallel applications which run poorly in uni-processor machines can be run on computational grids. Several middleware are available. Prominent ones for .NET 2.0 platform are Digipede and Alchemi.  

 

Here I am going to demonstrate a powerful application written in C# which makes use of Alchemi middleware. The application is written primarily to digitally sign a document using SHA512  authentication. Normally it will take a long amount of time but if written in a parallel fashion speedup will be significant.

 

The entire document/file to be processed is split into several blocks based on its size and the number of nodes available. Now digital signing (using .NET in-built System.Cryptography) is done. The output of this parallel processing is sent to a file.

 

Code:

 

using System;

using System.Data;

using System.Diagnostics;

using System.IO;

using System.Security.Cryptography;

using System.Text;

using System.Security.Permissions;

using System.Threading;

// Referring the Alchemi libraries

using Alchemi.Core;

using Alchemi.Core.Owner;

 

namespace Grypto

{

    namespace Crypt

    {

        internal static class Grypto

        {

            private static Process p;

            public static StringBuilder sb;

            public static FileStream fs;

            public static string fname;

            public static StreamWriter sw;

            public static FileStream output;

 

            // The Grid Application domain in which Grid threads are created

            private static GApplication Main_ga = new GApplication();

 

            [STAThread()]

            public static void Main()

            {

                p = new Process();

                int i = 1;

                int proc = 1;

                int execount = 0;

                double factor = 0.2;

                int numblocks = 50;

                char[] feed = new char[100001];

 

                output = new FileStream("output.txt", FileMode.Create, FileAccess.Write);

 

                sb = new StringBuilder();

                sw = new StreamWriter(output);

 

                // Name of the file to be signed

                Console.WriteLine("Enter the name of file");

                fname = Console.ReadLine();

                try

                {

                    fs = new FileStream(fname, FileMode.Open, FileAccess.Read);

                }

                catch (Exception ex)

                {

                    Console.WriteLine("File could not be read");

                    return;

                }

                StreamReader fr = new StreamReader(fs);

 

                Console.WriteLine("Welcome to Grid Framework");

                Console.ReadLine();

 

                //Connection is established

                GConnection gc = new GConnection("localhost", 9000, "user", "user");

 

                Main_ga.Connection = gc;

                // The processing class is added to the manifest

                Main_ga.Manifest.Add(new ModuleDependency(typeof(NCrypt).Module));

                Console.WriteLine("Connecting to the server....");

 

                // Event handlers when Gthreads and GApplication finish

                Main_ga.ThreadFinish += new GThreadFinish(tfin);

                Main_ga.ApplicationFinish += new GApplicationFinish(appfin);

 

                // Reading the document in blocks and adding Gthreads     

                while (!fr.EndOfStream)

                {

                    Console.WriteLine("Creating a {0} thread", i);

                    //Based on length the numblocks is decided at //runtime

                    while ((fs.Length / numblocks) > feed.Length)

                    {

                        numblocks = numblocks + System.Convert.ToInt32(Math.Floor(factor * numblocks));

                        Console.WriteLine("Number of blocks increased to " + numblocks.ToString());

                        execount = execount + 1;

                    }

                    if (execount >= 2)

                    {

                        // Change to the appropriate location in your machine

                        p.StartInfo.FileName = "C:\\Program Files\\Alchemi\\Executor\\Alchemi.ExecutorExec.exe";

                        p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;

                        try

                        {

                            p.Start();

                            Thread.Sleep(1000);

                        }

                        catch (Exception ex)

                        {

                            Console.WriteLine("Error " + ex.Message);

                            return;

                        }

                        if (factor > 0.02)

                        {

                            factor = factor - 0.02;

                        }

                        proc = proc + 1;

                        execount = 0;

                    }

                    fr.ReadBlock(feed, 0, fs.Length / numblocks);

                    Main_ga.Threads.Add(new NCrypt(i, feed));

                    i = i + 1;

                }

                fr.Close();

                fs.Close();

 

                // The Grid application starts  

                Main_ga.Start();

                Console.WriteLine("Done");

                try

                {

                    // ga.Stop()

                }

                catch (Exception ex)

                {

                    //Console.WriteLine("Exception " + ex.Message)

                }

                Console.ReadLine();

                sw.Close();

            }

            // Procedure invoked when Grid Application finishes

            public static void appfin()

            {

                Console.WriteLine("Application Finished");

            }

            // Procedure invoked when one Gthread finishes

            public static void tfin(GThread t)

            {

                NCrypt th = (NCrypt)t;

                // Displaying the results on the console

                Console.WriteLine("Hash value   " + BitConverter.ToString(th.@out));

                sw.WriteLine(BitConverter.ToString(th.@out));

            }

            // Procedure responsible for Hashing

            public static byte[] hash(byte[] input)

            {

                byte[] @out = null;

                @out = ((HMACSHA512)(CryptoConfig.CreateFromName("HMACSHA512"))).ComputeHash(input);

                return @out;

            }

        }

        // Gthreads are implemented here

        [Serializable()]

        public class NCrypt : GThread

        {

            public byte[] @out;

            private int i;

            private byte[] input;

            public int size;

            private string alg;

            private string s;

            private string str;

            //Every Gthread must implement a start method

            public override void Start()

            {

                input = (new UnicodeEncoding()).GetBytes(s);

                @out = Grypto.hash(input);

            }

            public NCrypt(int j, string isb)

            {

                i = j;

                s = System.Convert.ToString(isb);

            }

        }

    }

}

 

The Architecture of Alchemi primarily consists of a manager and several executors which are scheduled and managed by the manager. Each Grid application known as GApplication consists of several Grid threads (or Gthreads) whose implementation is defined through a serializable class  and added to the manifest.

 

In this way several applications can be run in parallel but the problem here is the Gthread implementation should be serializable but most of the .NET classes and namespaces are not. So the alternative is to write many of the procedures yourself.

 

More details  about Alchemi : http://www.gridbus.org/alchemi