Encryption

by MikeHogg 31. May 2012 09:50

A really interesting project had me implementing encryption algorithms for a Point Of Sale vendor interface.  It was the closest thing I’ve done to ‘computer science’ and I was fascinated at manipulating integers that were one thousand digits long.  The vendor used a symmetric encryption wrapped in an asymmetric method, plus an additional byte manipulation algorithm, making it a few layers deep.  I used a proven Big Integer implementation, and some of the MS encryption libraries for certain steps of the algorithm, but a lot of it was byte level manipulation. 

In one of my favorite parts of the algorithm, I used a bit shift operator.  Never found a use for that in Business Intelligence!

        private static byte[] ApplyOddParity(byte[] key)
        {
            for (var i = 0; i < key.Length; ++i)
            {
                int keyByte = key[i] & 0xFE; // 254? mask  
                var parity = 0;
                for (var b = keyByte; b != 0; b >>= 1) parity ^= b & 1; // shift right until empty, setting parity  xor b bitand 1
                key[i] = (byte)(keyByte | (parity == 0 ? 1 : 0)); // set byte = byte bitor (unchange if match) 1 if not parity or 0 for odd
            }
            return key;
        }
        public static string EncryptEAN(string eanhex, string decryptedmwkhex)
        {
            byte[] decryptedmwk = ConvertHexStringToByteArray(decryptedmwkhex);            
            byte[] asciiean = Encoding.ASCII.GetBytes(eanhex.PadRight(8, ' '));   
            
            TripleDESCryptoServiceProvider p = new TripleDESCryptoServiceProvider();
            p.Padding = PaddingMode.None;
            p.IV = new byte[8];
            // p.Mode = CipherMode.CBC; //  default 
            byte[] random = p.Key;     // testing: random = FDCrypt.ConvertHexStringToByteArray("95:e4:d7:7c:6d:6c:6c")         
            byte checksum = GetCheckSum(asciiean);            
            byte[] eanblock = new byte[16];
            Array.Copy(random, 0, eanblock, 0, 7);
            eanblock[7] = checksum;
            Array.Copy(asciiean, 0, eanblock, 8, 8);   // BitConverter.ToString(eanblock)
            p.Key = decryptedmwk;
            ICryptoTransform e = p.CreateEncryptor();
            
            byte[] result = e.TransformFinalBlock(eanblock, 0, 16);
            return BitConverter.ToString(result, 0).Replace("-",String.Empty);
        }
 
  public static string GetEncryptedMWK(string decryptedmwkhex, byte[] kek)
        {
            byte[] decryptedmwk = FDCrypt.ConvertHexStringToByteArray(decryptedmwkhex);
            TripleDESCryptoServiceProvider p = new TripleDESCryptoServiceProvider();
            p.Padding = PaddingMode.None;
            p.IV = new byte[8];
            // p.Mode = CipherMode.CBC; //  default 
            byte[] random = p.Key;     //random = FDCrypt.ConvertHexStringToByteArray("e7:11:ea:ff:a0:ca:c3:ba")
            p.Key = decryptedmwk;  // BitConverter.ToString(decryptedmwk)
            ICryptoTransform e = p.CreateEncryptor();
            byte[] checkvalue = e.TransformFinalBlock(new byte[8], 0, 8);       // BitConverter.ToString(checkvalue)   
            byte[] keyblock = new byte[40];
            Array.Copy(random, keyblock, 8);  
            Array.Copy(decryptedmwk, 0, keyblock, 8, 24);
            Array.Copy(checkvalue, 0, keyblock, 32, 8);   // BitConverter.ToString(keyblock)
             
            p.Key = kek;              
            e = p.CreateEncryptor();
            byte[] encryptedkeyblock = e.TransformFinalBlock(keyblock, 0, 40);   
            string result = BitConverter.ToString(encryptedkeyblock,0, 40);            
            return result.Replace("-",String.Empty); // should be 81 bytes inc null term?
        }

 

For testing, I built a UI in WPF.  Here you see how I wanted to encapsulate all the encryption stuff in a separate library (later to be used in a web site), yet needed a UI stub to go through the lengthy 18 step, two month long testing and certification process with the vendor.  I knew that UI could leverage my experience with the MVVM pattern in WPF to expose over 20 fields and half a dozen steps in fast iterations as we went through the vetting process, and the WPF UI became more of a helpful tool than a code maintenance drain like most UI’s. 

 

 

 

 

 

 

 

 

 

 


Tags:

WPF | C# | Encryption

Password hashing

by MikeHogg 11. May 2012 15:08

After some research this year, since the last time I had to write any password system was in 2006 or 2007, I am under the impression that the BCrypt library is the defacto standard in encryption and is available in C#.  the main point going for BCrypt is that it has a difficulty factor built in.  This prevents super hardware from brute forcing requests at sub millisecond attempts if it can get to it, and so limits dictionary attacks. 

 

Using it is simple.  I drop this BCrypt file into each of my projects.  BTW in it you will find the header with links to the project doc and license info.

BCrypt.cs (34.97 kb)

 

Now, your Membership provider just needs to store passwords BCrypted, like so

       public static bool SavePassword(string username, string newPassword)
        {
            string salt = lib.BCrypt.GenerateSalt(6);
            string hash = lib.BCrypt.HashPassword(newPassword, salt);
 
            return lib.DatabaseHelper.SavePassword(username, hash);
        }

(the SALT is the difficulty factor)

... and use the Bcrypt library to test passwords with its verify() method like this

public override bool ValidateUser(string username, string password)
{
    string hash = GetPassword(username, null);
    if (hash.Equals(string.Empty)) return false;
    return lib.BCrypt.Verify(password, hash);
}

Tags:

C# | Encryption

Using a heartbeat to find time of death on constantly changing databases

by MikeHogg 1. April 2008 20:31

Another unusual request I had one day that I enjoyed writing.  The team I worked on employed up to a dozen copies of the same database, some of them in different stages of testing like Prod and UAT and Stage and Stage2, and some of them purposed for data analysis or short investigative projects. 

Only some of these were active, in that they were running our continuous batch processing procedures, which continually imported data from upstream systems and processed it.  At times we wanted to know, in the cases of the inactive systems, when they were taken offline, and made inactive.  When they stopped receiving upstream data. 

So I set up a console application that had two functions.  The first was to update a particular database with a timestamp, running every five minutes or so.  I slipped the command for this into the same scheduler that ran the batch processing, so it would only run on Active databases.  Also, the timestamp was to be encrypted. It was the case sometimes that we absolutely needed to know that our timestamp wasn’t modified by outside sources.  It might be a little overboard but it was an interesting project.

The second part was a method to find this out from any database.  So this same console app, dropped in a NAS script location, allowed anybody on the network to find on their command line the actual last timestamp, decrypted, of a given database.

Here are the two routines:

        static private int updateDB()
        {
            byte[] key = {};
            byte[] IV = {  0x49, 0xCD, 0x24, 0x37, 0x95, 0xDB, 0xFE, 0xBD };
            String systimestamp;
            String timecode;
             
            OracleCommand myCmd = new OracleCommand("",Conn);
            try
            {
                
                key = System.Text.Encoding.UTF8.GetBytes("pacmanlx");
                 
                
                DESCryptoServiceProvider myDES = new DESCryptoServiceProvider();
                //Rijndael myR = Rijndael.Create();
                
                byte[] inputString = Encoding.UTF8.GetBytes(DateTime.Now.ToString( "MMM-dd" ));
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                CryptoStream cs = new CryptoStream(ms, myDES.CreateEncryptor(key, IV), CryptoStreamMode.Write);
                cs.Write(inputString, 0, inputString.Length);
                cs.FlushFinalBlock();
                //encrypt this baby
                timecode = Convert.ToBase64String(ms.ToArray());
                
                //not this one           
                systimestamp = DateTime.Now.ToString();
                myCmd.CommandText = "update some.valid_general_cd v set v.decode = '" +
                systimestamp + "', column_cat_cd = '" + timecode + "' where v.code_id = 4444";
                Conn.Open();
                int myReturn = myCmd.ExecuteNonQuery();
                myCmd.Dispose(); 
                Conn.Close();
                return myReturn;
                
            }
            catch (Exception ex) {
                if (Conn.State == System.Data.ConnectionState.Open)
                {
                    Conn.Close();
                }
                
                throw new Exception(ex.ToString());
            }
        }
        static private void decryptTime(string db)
        {
            byte[] key = { };
            byte[] IV = {  0x49, 0xCD, 0x24, 0x37, 0x95, 0xDB, 0xFE, 0xBD };
            byte[] inputByteArray = { };
            OracleConnection Conn = new OracleConnection("Data Source=" + db + ".somecorp.net;User Id=somedbuser;Password=password;");
            OracleCommand myCmd = new OracleCommand("",Conn);
            String outputString;
            try
            {
                key = System.Text.Encoding.UTF8.GetBytes("pacmanlx");
                DESCryptoServiceProvider myDES = new DESCryptoServiceProvider();
                //Rijndael myR = Rijndael.Create();
                myCmd.CommandText = "select v.column_cat_cd from some.valid_general_cd v where v.code_id = 4444";
                Conn.Open();
                
                OracleDataReader myReader = myCmd.ExecuteReader();
                myReader.Read();
                //object = myReader.getsomething
                outputString = myReader.GetString(0);
                
                //decrypt object
                inputByteArray = Convert.FromBase64String(outputString);
                
                //now decrypt the regular string
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                CryptoStream cs = new CryptoStream(ms, myDES.CreateDecryptor(key, IV),
                                               CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                
                System.Text.Encoding encoding  = System.Text.Encoding.UTF8;
                //write date to console
                Console.WriteLine(encoding.GetString(ms.ToArray()));
                myReader.Close();
                
            }
            catch (Exception ex)
            {
                if (Conn.State == System.Data.ConnectionState.Open)
                {
                    Conn.Close();
                }
                Console.WriteLine(ex.ToString());
            }

About Mike Hogg

Mike Hogg is a c# developer in Brooklyn.

More Here

Favorite Books

This book had the most influence on my coding style. It drastically changed the way I write code and turned me on to test driven development even if I don't always use it. It made me write clearer, functional-style code using more principles such as DRY, encapsulation, single responsibility, and more. amazon.com

This book opened my eyes to a methodical and systematic approach to upgrading legacy codebases step by step. Incrementally transforming code blocks into testable code before making improvements. amazon.com

More Here