4

To start off, I am still learning object oriented programming. Ok, I have a combo box with the different types of symmetric algorithms.

private void Form3_Load(object sender, EventArgs e)
{
    openencrypt();
    comboBox1.Items.Add("AES");
    comboBox1.Items.Add("DES");
    comboBox1.Items.Add("Rijndael");
    comboBox1.Items.Add("RC2");
    comboBox1.Items.Add("Triple DES");
    comboBox1.SelectedIndex = 0;
}

Then I have my encrypt function checking what types they are.

byte[] hpass;
string nFilepath = Set.nfilepath;
FileStream Open = new FileStream(oFilepath, FileMode.Open, FileAccess.Read);
FileStream Save = new FileStream(nFilepath, FileMode.OpenOrCreate, FileAccess.Write);
SHA512 sh512 = new SHA512Managed();
hpass = sh512.ComputeHash(Encoding.ASCII.GetBytes(textBox1.Text));
PasswordDeriveBytes pdb = new PasswordDeriveBytes(hpass, hash);

if (comboBox1.SelectedIndex.Equals(0))
{
    Aes alg = Aes.Create();
    alg.Key = pdb.GetBytes(32);
    alg.IV = pdb.GetBytes(16);
}
if (comboBox1.SelectedIndex.Equals(1))
{
    DES alg = DES.Create();
    alg.Key = pdb.GetBytes(32);
    alg.IV = pdb.GetBytes(16);
}
if (comboBox1.SelectedIndex.Equals(2))
{
    Rijndael alg = Rijndael.Create();
    alg.Key = pdb.GetBytes(32);
    alg.IV = pdb.GetBytes(16);
}

But when I don't want to have to put a crypto stream in each if statement. So is there a way to offload the checking to a function and return a symmetricalgorithm type? With the Key and IV? Am I going about this completely wrong?## Heading ##

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262

2 Answers2

2

A more object oriented approach would be:

Create an algorithm interface to be displayed in your combo box:

public interface IAlgorithmItem
{
    SymmetricAlgorithm CreateAlgorithm();

    string DisplayName { get; }
}

Then, create a new class for each desired algorithm:

public class AesAlgorithm : IAlgorithmItem
{
    public AesAlgorithm()
    {
    }

    public SymmetricAlgorithm CreateAlgorithm()
    {
        return Aes.Create();
    }

    public string DisplayName
    {
        get { return "AES"; }
    }
}

public class RijndaelAlgorithm : IAlgorithmItem
{
    public SymmetricAlgorithm CreateAlgorithm()
    {
        return Rijndael.Create(); 
    }

    public string DisplayName
    {
        get { return "Rijndael"; }
    }
}

// ...

Then, you can create a new list of items:

var listItems = new List<IAlgorithmItem>() { new AesAlgorithm(), new RijndaelAlgorithm() };

Then you can bind your combo box to this list:

comboBox1.DataSource = listItems;
comboBox1.DisplayMember = "DisplayName";

Later, you can reference the selected item:

var algorithmItem = (IAlgorithmItem)comboBox1.SelectedItem;
var algorithm = algorithmItem.CreateAlgorithm();

EDIT: Updated with Will's suggestion of using an interface rather than an abstract base class. EDIT 2: Updated to use a create method rather than property, as the result of the operation will create a new algorithm each time it is accessed.

armen.shimoon
  • 6,303
  • 24
  • 32
2

Well, my first inclination was to give you Wikipedia links to the factory method and abstract factory patterns (there, I did it still), but since you say you're a beginner, let's not bring out the big guns upfront.

Basically, what you need is to find a common trait of all encryption algorithms and create a method that will return an object instance that has this common trait. The manifestation of such a trait can be either an abstract class or an interface in C#, and you're in luck, all your selected encryptions derive from SymmetricAlgorithm ("luck" is probably an insult to the designers of System.Security.Cryptography, but I'm sure they'd forgive me for the sake of illustration ;).

So, just refactor your code by introducing a new method, possibly along these lines:

private SymmetricAlgorithm GetAlgorithm(int index)
{
  switch (index)
  {
    case 0:
      return Aes.Create();
    case 1:
      return DES.Create();
    case 2:
      return Rijndael.Create();
    default:
      throw new NotSupportedException("unknown algorithm");
  }
}

You can easily figure out how to use this new method from the rest of your code.

Alan
  • 6,501
  • 1
  • 28
  • 24
  • I can appreciate the simplicity of this design. – ChaosPandion Sep 09 '12 at 08:46
  • @ChaosPandion: Thanks. I feel the other answers, while possibly better from an OOP point of view, may be daunting to a beginner. One step at a time, whetting their appetite for more :) – Alan Sep 09 '12 at 08:50
  • Thank you very much! I think this will work, and switch cases are something I know about! C# is very different than the programming languages I know, so it's been taking some getting used to. Thank you for being so supportive. – user1657838 Sep 09 '12 at 22:47
  • @user1657838: You're welcome, and I'm really glad I could help. – Alan Sep 11 '12 at 20:10