views:

202

answers:

3

The idea is to produce utility class , so that whenever the guys hack the best currently known algorithms and new one comes to the market the only think that the Developer would have to do is to add the NewHighTechEncryptingAlgorithm_Encryptor class and change a global application setting for NewHighTechEncryptingAlgorithm_As_String

so that the call would be string myNewEncryptedString = Encryptor.Encrypt(StringToEncrypt , strAlgorithmName)

Edit: I removed the old code and pasted the answer, provided by rwwilden with the calling code

I quess the proper wording would be "Enhashing" as oppose of "Encryption" since no salt is envolved here ... this seems to be the best solution according to the proposed "specs"

 using System;
 using System.Text;
 using System.Security.Cryptography;

 namespace GenApp.Utils.Security
 {

 /// <summary>
 /// Summary description for Encrypter
 /// </summary>
 public class Encrypter 
 {
 /// <summary>
 /// Encrypts according to the passed plain name for hasing algorithm
 /// see CryptoConfig class from MSDN for more details
 /// </summary>
 /// <param name="strPlainTxt">the plain text to encrypt</param>
 /// <param name="strAlgorithmName">The plain name of the hashing algorithm </param>
 /// <returns> the encrypted string </returns>
 public static string Encrypt ( string strPlainTxt, string strAlgorithmName )
 {
  string strHashedTxt = String.Empty;
  byte[] bytPlain = System.Text.Encoding.UTF8.GetBytes ( strPlainTxt );


  using (HashAlgorithm objAlgorithm = HashAlgorithm.Create ( strAlgorithmName ))
  {
   byte[] bytHash = objAlgorithm.ComputeHash ( bytPlain );
   strHashedTxt = Convert.ToBase64String ( bytHash );
   return strHashedTxt; 
  } 

 } //eof method 


 ///// OLD CODE - REQUIRES RECODING 
 ///// <summary>
 ///// Encrypts according to the passed plain name for hasing algorithm
 ///// see CryptoConfig class from MSDN for more details
 ///// </summary>
 ///// <param name="strPlainTxt">the plain text to encrypt</param>
 ///// <param name="strAlgorithmName">The plain name of the hashing algorithm </param>
 ///// <returns> the encrypted string </returns>
 //public static string Encrypt ( string strPlainTxt, string strAlgorithmName )
 //{
 //  string strHashedTxt = String.Empty;
 //  byte[] bytPlains = System.Text.Encoding.UTF8.GetBytes ( strPlainTxt );
 //  byte[] bytHash;
 //  //CryptoConfig objCryptoConfig = new CryptoConfig ();


 //  switch (strAlgorithmName)
 //  {
 //    case "SHA1":
 //      SHA1CryptoServiceProvider objProvForSHA1alg =
 //        (SHA1CryptoServiceProvider)CryptoConfig.CreateFromName ( strAlgorithmName );


 //      bytHash = objProvForSHA1alg.ComputeHash ( bytPlains );
 //      objProvForSHA1alg.Clear ();
 //      strHashedTxt = Convert.ToBase64String ( bytHash );

 //      break;
 //    case "MD5" :

 //      MD5CryptoServiceProvider objProvForMD5alg =
 //        (MD5CryptoServiceProvider)CryptoConfig.CreateFromName ( strAlgorithmName );

 //      bytHash = objProvForMD5alg.ComputeHash ( bytPlains );
 //      strHashedTxt = Convert.ToBase64String ( bytHash );
 //      objProvForMD5alg.Clear ();


 //      break; 

 //  } //eof switch

 //  if (String.IsNullOrEmpty ( strHashedTxt ))
 //    throw new Exception ( "Encryption provider called by invalide simple name " );


 //  return strHashedTxt;
 //} //eof method 


 } //eof class 


 class Program
 {
 static void Main ( string[] args )
 {
  string strPlainTxt = "UnEncryptedText";
  string strAlgorithmName = "SHA1"; //the type of al
  string strHashedTxt = String.Empty;

  //START WITH ONE ALGORITHM
  Console.WriteLine ( "Using the " + strAlgorithmName + " START " );
  Console.WriteLine ( "The plain text is " + strPlainTxt );
  Console.WriteLine ( "The encrypting algorithm is " + strAlgorithmName );
  strHashedTxt = Encrypter.Encrypt ( strPlainTxt, strAlgorithmName );
  Console.WriteLine ( "The hashed text is " + strHashedTxt );
  Console.WriteLine ( "Using the " + strAlgorithmName + " END " );

  //NOW CHANGE THE ALGORITHM
  strAlgorithmName = "MD5";
  Console.WriteLine ( "Using the " + strAlgorithmName + " START " );
  Console.WriteLine ( "The plain text is " + strPlainTxt );
  Console.WriteLine ( "The encrypting algorithm is " + strAlgorithmName );
  strHashedTxt = Encrypter.Encrypt ( strPlainTxt, strAlgorithmName );
  Console.WriteLine ( "The hashed text is " + strHashedTxt );
  Console.WriteLine ( "Using the " + strAlgorithmName + " END " );


  strAlgorithmName = "SHA256";
  Console.WriteLine ( "Using the " + strAlgorithmName + " START " );
  Console.WriteLine ( "The plain text is " + strPlainTxt );
  Console.WriteLine ( "The encrypting algorithm is " + strAlgorithmName );
  strHashedTxt = Encrypter.Encrypt ( strPlainTxt, strAlgorithmName );
  Console.WriteLine ( "The hashed text is " + strHashedTxt );
  Console.WriteLine ( "Using the " + strAlgorithmName + " END " );


  Console.WriteLine ( "Hit enter to exit" );
  Console.ReadLine ();
 }

 }
 } //eof namespace
+1  A: 

What's the point in //eof class and //eof namespace trash?

For the record: what you're trying to achieve is basically a somewhat limited plugin architecture. See MEF on how this can be done.

And by the way, are you aware of ICryptoTransform?

Anton Gogolev
Thanks for answering !*** What's the point in //eof class and //eof namespace trash?Coder's blindness ; )Thanks , I would have to check it out ...
YordanGeorgiev
+2  A: 

You should take a look at the CryptoConfig class. Especially the method CreateFromName. It provides a way to obtain a cryptographic algorithm based on a name (that you supply in your configuration). Changing the name in your configuration automatically changes the algorithm used.

If you have made a choice on whether to use symmetric or asymmetric encryption, you should use the more specific SymmetricAlgorithm.Create(string) or AsymmetricAlgorithm.Create(string) methods.

Since you require a hashing solution, you should use HashAlgorithm.Create(string). The reason for implementing it as I do below is that you do not have to change any code when you decide to use another hashing algorithm. In your code you have to add another case statement.

public static string Encrypt(string toEncrypt, string algorithmName)
{
    byte[] bytePlain = System.Text.Encoding.UTF8.GetBytes ( strPlainTxt );
    using (HashAlgorithm algorithm = HashAlgorithm.Create(algorithm))
    {
        byte[] byteHash = algorithm.ComputeHash(bytePlain);
        string strHashedTxt = Convert.ToBase64String (byteHash);
        return strHashedTxt;
    }
}
Ronald Wildenberg
Iquess later on the SymmetricAlgorithm.Create(string) or AsymmetricAlgorithm.Create(string) methods must be implemented ...
YordanGeorgiev
+2  A: 

I'd suggest a copy of Resharper or Coderush to fix that coders blindness :) Brace highlighting comes in the box.

Also, this is classic, or basic, interfaces + factory pattern. As others have said, the MEF and ICryptoTransform is most likely the cleanest place to start, as the framework provides it for you, but if you want to know the basics:

Make an interface:

public interface IEncrypter {
  string Encrypt(string plaintext);
}

then implement it:

public class MD5Encrypter : IEncrypter {
  public string Encrypt(string plaintext) {
    //code goes here.
  }
}

public class SHA1Encrypter : IEncrypter {
  public string Encrypt(string plaintext) {
    //code goes here.
  }
}

then, make a factory:

public class EncryptionFactory {
  public static IEncrypter GetEncrypter() {
    //work out which one to return, maybe based on a config value?

    // I'm just going to return an MD5, but you'd want to use a switch statement etc
    // to decide which one to return.

    return new MD5Encrypter();
  }
}

And use it like this:

IEncrypter encrypter = EncryptionFactory.GetEncrypter();
string garbageText = encrypter.Encrypt("Hello, world");

All you change is the factory, or better yet, the config the factory reads in, to make it use something else. Hell, you can base it on the time of day if you really want :) The code you write which uses the interface doesn't care what the object actually is - it just cares that is has a: string Encrypt(string) method.

The MEF does this for you, in some ways.

Using the interfaces also means you could return a dummy, fake IEncrypter which does nothing, so you can write unit tests against it without actually doing the encryption. Not SUPER useful in this case, but it's good practice in general.

Also, you could use @rwwilden's suggestion in the Factory to generate it - you read a string from config, and use the Asymetric/Symetric create method thing he's talking about to create the underlying class.....

Nic Wise